Flutter中如何从ElevatedButton的onPressed调用带参数的命名函数?
Flutter中setState调用报错的问题分析与解决
可行写法
ElevatedButton( onPressed: () => { setState(() { userInputTextControllers.removeAt(index); userTextList.removeAt(index); }) }, child: const Text("R")) )
不可行写法
ElevatedButton( onPressed: f(index), child: const Text("R")) ) f(int index) { setState(() { userInputTextControllers.removeAt(index); userTextList.removeAt(index); }) }
其中index来自ListView,第二种写法会抛出错误:setState can't be called during build。
问题原因
第二种写法里,onPressed: f(index)是直接执行了函数f,而不是把函数作为点击回调传递给onPressed。在Flutter构建UI的build阶段,代码执行到这一行时会立刻调用f函数,而f内部调用的setState会触发UI重建,导致当前build过程未完成时又发起新的build,违反了Flutter的生命周期规则,因此抛出错误。
而第一种写法用匿名函数() => {...}作为回调,只有当按钮被点击时才会执行里面的代码,此时已经脱离了build阶段,所以setState的调用是安全的。
解决方法
要实现将代码放入带index参数的独立命名函数中,有两种常用方式:
方式一:让命名函数返回一个函数
让f函数返回一个VoidCallback类型的函数,这样onPressed接收的是一个函数对象,而非函数执行结果:
ElevatedButton( onPressed: f(index), child: const Text("R") ) VoidCallback f(int index) { return () { setState(() { userInputTextControllers.removeAt(index); userTextList.removeAt(index); }); }; }
方式二:用匿名函数包裹命名函数调用
通过匿名函数包装对f的调用,确保只有点击时才执行f:
ElevatedButton( onPressed: () => f(index), child: const Text("R") ) void f(int index) { setState(() { userInputTextControllers.removeAt(index); userTextList.removeAt(index); }); }
内容的提问来源于stack exchange,提问作者Aquarius_Girl
相关产品推荐
相关产品推荐

