Flutter/Dart - 如何从不同文件中的另一个 StatefulWidget 更改 StatefulWidget 的状态?
Flutter/Dart - How can I change the State of a StatefulWidget from another StatefulWidget in a different file?
背景: 我有一个用于导航栏的 StatefulWidget,它将当前页面的图标显示为活动状态。如果用户从导航栏中单击不同的图标,它已经正确更新。但如果用户单击导航栏外的按钮,我也需要它来更新活动图标,该按钮的代码位于不同的 StatefulWidget 中。
为此,我设想按钮的功能应该从导航栏 StatefulWidget 调用一个函数,该函数使用 setState 和作为参数传递的索引来更新活动图标。但是,到目前为止,我的尝试没有奏效。
发生以下错误:
The following assertion was thrown while handling a gesture:
I/flutter (24216): setState() called in constructor: TabsState#1bf6b(lifecycle state: created, no widget, not mounted)
I/flutter (24216): This happens when you call setState() on a State object for a widget that hasn't been inserted into
I/flutter (24216): the widget tree yet. It is not necessary to call setState() in the constructor, since the state is
I/flutter (24216): already assumed to be dirty when it is initially created.`}
来自父小部件的代码是:
[...]
Tabs({Key key, this.menuScreenContext, this.initialIndex}) : super(key: key);
final int initialIndex;
@override
TabsState createState() => TabsState();
}
class TabsState extends State<Tabs> {
PersistentTabController controller;
@override
void initState() {
super.initState();
controller = PersistentTabController(initialIndex: widget.initialIndex);
}
List<Widget> _buildScreens() {
return [
HomeScreen(),
[...]
void updateIndex(int index) {
setState(() {
controller.index = index;
});
}
}
来自子控件的代码(class _HomeScreenState extends State):
[...]
CustomButton(
function: () {
final tabsState = TabsState();
tabsState.updateIndex(2);
[...]
我试图通过在调用 setState() 之前在子小部件上调用 initState() 来解决它,但这没有用,据我所知,它创建了另一个与 Stateful Widget 关联的 State 对象,这似乎喜欢这种情况下的错误方法,因为我只想更改现有导航栏对象的状态。
我的问题是:如何从位于不同文件中的另一个 StatefulWidget 中的 Button 函数成功调用此函数 updateIndex(int index),它使用 setState 更新导航栏活动图标?
我做到了!
根据这个问题的答案(),我了解到访问不同有状态小部件的状态的方法是:
1-> 使用查找该类型的祖先的 findAncestorStateOfType 声明您要在子小部件有状态小部件上更改的状态 class。例如:
class HomeScreen extends StatefulWidget {
static TabsState of(BuildContext context) =>context.findAncestorStateOfType<TabsState>();
2-> 在此有状态小部件的状态 class 内的任何需要的地方调用该函数,引用有状态小部件 class 并使用“of(context)”。例如:
function: () {
HomeScreen.of(context).updateIndexFromCart(2);
3->这个函数应该位于你之前提到的stateful widget的stateclass里面,然后才可以正常使用setState。例如:
void updateIndexFromCart(int index) {
setState(() {
controller.index = index;
cartScreenFlag = true;
});
}
背景: 我有一个用于导航栏的 StatefulWidget,它将当前页面的图标显示为活动状态。如果用户从导航栏中单击不同的图标,它已经正确更新。但如果用户单击导航栏外的按钮,我也需要它来更新活动图标,该按钮的代码位于不同的 StatefulWidget 中。 为此,我设想按钮的功能应该从导航栏 StatefulWidget 调用一个函数,该函数使用 setState 和作为参数传递的索引来更新活动图标。但是,到目前为止,我的尝试没有奏效。 发生以下错误:
The following assertion was thrown while handling a gesture:
I/flutter (24216): setState() called in constructor: TabsState#1bf6b(lifecycle state: created, no widget, not mounted) I/flutter (24216): This happens when you call setState() on a State object for a widget that hasn't been inserted into I/flutter (24216): the widget tree yet. It is not necessary to call setState() in the constructor, since the state is
I/flutter (24216): already assumed to be dirty when it is initially created.`}
来自父小部件的代码是:
[...]
Tabs({Key key, this.menuScreenContext, this.initialIndex}) : super(key: key);
final int initialIndex;
@override
TabsState createState() => TabsState();
}
class TabsState extends State<Tabs> {
PersistentTabController controller;
@override
void initState() {
super.initState();
controller = PersistentTabController(initialIndex: widget.initialIndex);
}
List<Widget> _buildScreens() {
return [
HomeScreen(),
[...]
void updateIndex(int index) {
setState(() {
controller.index = index;
});
}
}
来自子控件的代码(class _HomeScreenState extends State):
[...]
CustomButton(
function: () {
final tabsState = TabsState();
tabsState.updateIndex(2);
[...]
我试图通过在调用 setState() 之前在子小部件上调用 initState() 来解决它,但这没有用,据我所知,它创建了另一个与 Stateful Widget 关联的 State 对象,这似乎喜欢这种情况下的错误方法,因为我只想更改现有导航栏对象的状态。
我的问题是:如何从位于不同文件中的另一个 StatefulWidget 中的 Button 函数成功调用此函数 updateIndex(int index),它使用 setState 更新导航栏活动图标?
我做到了!
根据这个问题的答案(
1-> 使用查找该类型的祖先的 findAncestorStateOfType 声明您要在子小部件有状态小部件上更改的状态 class。例如:
class HomeScreen extends StatefulWidget {
static TabsState of(BuildContext context) =>context.findAncestorStateOfType<TabsState>();
2-> 在此有状态小部件的状态 class 内的任何需要的地方调用该函数,引用有状态小部件 class 并使用“of(context)”。例如:
function: () {
HomeScreen.of(context).updateIndexFromCart(2);
3->这个函数应该位于你之前提到的stateful widget的stateclass里面,然后才可以正常使用setState。例如:
void updateIndexFromCart(int index) {
setState(() {
controller.index = index;
cartScreenFlag = true;
});
}