在生成过程中调用了Flutter错误setState()或markNeedsBuild().当使用Getx GetxCo



我有一个计数器小部件,代码如下

import 'dart:math' as math;
import 'package:flutter/material.dart';
import 'package:erp_app/icons/PlutusIcons.dart';
class Counter extends StatefulWidget {
final int? value;
final ValueChanged<int>? onValueChanged; 
final int? maximum;
final int? minimum;
final double? buttonSize;
final double? textSize;
final bool? editable; 
final TextEditingController? customTextController;
Counter({
Key? key,
this.value,
this.maximum,
this.minimum,
this.onValueChanged,
this.buttonSize,
this.textSize,
this.editable,
this.customTextController,
}) : super(key: key);
@override
_CounterState createState() => _CounterState();
}
class _CounterState extends State<Counter> {
int _currentValue = 0;
TextEditingController _textController = TextEditingController();
FocusNode _textFocusNode = FocusNode();
@override
void didUpdateWidget(covariant Counter oldWidget) {
if (widget.value != null) {
_currentValue = _verifyInputVal(widget.value!);
_textController.text = _currentValue.toString();
_notifyValueChange(_currentValue);
}
super.didUpdateWidget(oldWidget);
}
@override
void initState() {

if (widget.customTextController != null) {
_textController = widget.customTextController!;
}

_handleFocusNodeEvent();
int initValue = widget.value ?? 0;
initValue = _verifyInputVal(initValue);
_currentValue = initValue;
_textController.text = initValue.toString();
_notifyValueChange(initValue);
super.initState();
}

@override
void dispose() {

if (widget.customTextController == null) {
_textController.dispose();
}
_textFocusNode.dispose();
super.dispose();
}
void _handleFocusNodeEvent() {
_textFocusNode.addListener(() {
if (_textFocusNode.hasFocus == false && widget.editable != null && widget.editable == true) {

setState(() {
_textController.text = _currentValue.toString();
});
}
});
}
void _increase() {
if (widget.maximum != null && _currentValue >= widget.maximum!) {
return;
}
_currentValue += 1;
_notifyValueChange(_currentValue);
setState(() {
_currentValue = _currentValue;
_textController.text = _currentValue.toString();
});
}
void _decrease() {
if (widget.minimum != null && _currentValue <= widget.minimum!) {
return;
}
_currentValue -= 1;
_notifyValueChange(_currentValue);
setState(() {
_currentValue = _currentValue;
_textController.text = _currentValue.toString();
});
}
bool _increaseIsDisabled() {
if (widget.maximum == null) {
return false;
}

return widget.maximum != null && _currentValue >= widget.maximum!;
}
bool _decreaseIsDisabled() {
if (widget.minimum == null) {
return false;
}

return widget.minimum != null && _currentValue <= widget.minimum!;
}

int _verifyInputVal(int val) {
int result = 0;
int? minimum = widget.minimum;
int? maximum = widget.maximum;
if (minimum != null) {
result = math.max(minimum, val);
}
if (maximum != null) {
result = math.min(result, maximum);
}
return result;
}
void _notifyValueChange(int value) {
widget.onValueChanged?.call(value);
}
void _inputOnChange(String val) {
int? num = int.tryParse(val);
if (num == null) {
return;
}

_currentValue = _verifyInputVal(num);
if (widget.onValueChanged != null) {
widget.onValueChanged!(_currentValue);
}
setState(() {
_currentValue = _currentValue;
});
}
@override
Widget build(BuildContext context) {
return Container(
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Expanded(
child: IconButton(
constraints: BoxConstraints(
minWidth: widget.buttonSize ?? 20.0,
minHeight: widget.buttonSize ?? 20.0,
),
color: _decreaseIsDisabled() ? Colors.black45 : Colors.blue,
disabledColor: Colors.grey,
onPressed: _decreaseIsDisabled() ? null : _decrease,
icon: Icon(
PlutusIcons.decrease,
size: widget.buttonSize ?? 20.0,
),
),
),
Container(
padding: EdgeInsets.only(left: 5.0, right: 5.0),
width: 80.0,
child: TextFormField(
keyboardType: TextInputType.number,
controller: _textController,
focusNode: _textFocusNode,
onChanged: _inputOnChange,
enabled: widget.editable ?? false,
style: TextStyle(
fontSize: widget.textSize,
),
textAlign: TextAlign.center,
),
),
Expanded(
child: IconButton(
constraints: BoxConstraints(
minWidth: widget.buttonSize ?? 20.0,
minHeight: widget.buttonSize ?? 20.0,
),
color: _increaseIsDisabled() ? Colors.black45 : Colors.blue,
disabledColor: Colors.grey,
onPressed: _increaseIsDisabled() ? null : _increase,
icon: Icon(
PlutusIcons.plus,
size: widget.buttonSize ?? 20.0,
),
),
),
],
),
);
}
}

我在GetxPage中使用这个小部件


class page extends StatelessWidget {
Widget build(BuildContext context) {
return GetBuilder<PageLogic>(
init: PageLogic(), 
logic => Counter(
editable: true,
value: logic.systemStockNum,
buttonSize: 28.0,
minimum: 0,
onValueChanged: logic.handleCounterChange,
));
}
}

我将valueChanged回调传递到Counter小部件,然后当changeHandler调用时,我将更改GetxController属性并更新

class PageLogic extends GetxController {
int currentValue = 0;
void handleCounterChange(int value) {
currentValue = value;
update();
}
}

然后发出错误,如何解决错误?为什么会出现错误?

这意味着即使初始小部件已经加载,您也要尝试刷新页面。

为了防止在构建过程中调用setState,方法已经在进行中,您可以在调用setState之前检查初始小部件是否正确安装。要做到这一点,只需用if语句包装您的setState,如下所示:

if(mounted){
setState((){
});
}

如果某个方法将重建正在渲染的一些小部件,则不能调用initState内部的方法。

要解决这个问题,您应该从控制器中使用onReady方法。

您应该将所有变量移动到控制器类中。

class PageLogic extends GetxController {
int currentValue = 0;
// move all your veriables here (TextEditingControllers, all)

@override
void onReady(){
make you logic for initialization here

super.onReady();
}

void handleCounterChange(int value) {
currentValue = value;
update();
}

}

取回控制器并在页面内使用

final pageLogic = PageLogin();

相关内容

最新更新