在 Flutter 中管理动态小部件状态的正确方法
Correct way to manage state on dynamic widgets in Flutter
我在 sqlite 中有一个类别列表,我在 streambuilder 中获取了这些行,然后,我创建了一个开关小部件列表。在每个开关小部件 ontoggle 事件中,我更改源值并调用 setState 方法,但是,这会导致构建事件的执行并重置所有开关小部件值。之后,我更改了代码以将所有小部件存储在一个变量中,如果小部件存在,则在 streambuild 中,return 小部件列表,这几乎可以正常工作,这会更新源中的小部件值,但是,小部件看起来像如果它们是假的。
有人知道吗?
此致
StreamBuilder<List<Category>>( <--- this code is in build event
stream: _catBloc.categoriesStream,
builder: (BuildContext context, AsyncSnapshot<List<Category>> snapshot) {
if(!snapshot.hasData) {
return Container(
height: _size.height,
width: _size.width,
child: Center(
child: CircularProgressIndicator(),
),
);
} else if(_categoriesLinked.isEmpty){ <-- this is a map with the list of id and name
column = _createCategories(snapshot.data, widthSwitch);
return column;
} else {
return column;
}
},
),
Container( <-- this is inside _createCategories method
width: width,
child: Row(
children: [
FlutterSwitch(
width: _size.width * 0.06,
height: _size.height * 0.02,
toggleSize: 20.0,
value: _categoriesLinked[e.id],
showOnOff: false,
padding: 2.0,
activeColor: Color.fromRGBO(88, 203, 143, 0.25),
inactiveColor: Color.fromRGBO(224, 233, 240, 0.50),
activeToggleColor: Color.fromRGBO(88, 203, 143, 1.0),
inactiveToggleColor: Color.fromRGBO(78, 88, 96, 0.50),
onToggle: (val) => setState(() {
_categoriesLinked[e.id] = val;
}),
),
SizedBox(width: _size.width * 0.01,),
Flexible(child: Text("${ e.id}. ${ e.name}"))
]
),
)
在这种情况下,您应该重构您的代码,以便将开关创建为另一个小部件,使它们只重建自己。
对于开关的状态,您可以简单地使用 GlobalKey<MySwitchState>
从父级获取它,以便在 onPressed
方法期间访问子级状态,例如:mySwitchKey.currentState
您绝对应该避免在方法内部构建有状态小部件。如果您觉得需要一种方法,请创建一个新的小部件。
我在 sqlite 中有一个类别列表,我在 streambuilder 中获取了这些行,然后,我创建了一个开关小部件列表。在每个开关小部件 ontoggle 事件中,我更改源值并调用 setState 方法,但是,这会导致构建事件的执行并重置所有开关小部件值。之后,我更改了代码以将所有小部件存储在一个变量中,如果小部件存在,则在 streambuild 中,return 小部件列表,这几乎可以正常工作,这会更新源中的小部件值,但是,小部件看起来像如果它们是假的。
有人知道吗?
此致
StreamBuilder<List<Category>>( <--- this code is in build event
stream: _catBloc.categoriesStream,
builder: (BuildContext context, AsyncSnapshot<List<Category>> snapshot) {
if(!snapshot.hasData) {
return Container(
height: _size.height,
width: _size.width,
child: Center(
child: CircularProgressIndicator(),
),
);
} else if(_categoriesLinked.isEmpty){ <-- this is a map with the list of id and name
column = _createCategories(snapshot.data, widthSwitch);
return column;
} else {
return column;
}
},
),
Container( <-- this is inside _createCategories method
width: width,
child: Row(
children: [
FlutterSwitch(
width: _size.width * 0.06,
height: _size.height * 0.02,
toggleSize: 20.0,
value: _categoriesLinked[e.id],
showOnOff: false,
padding: 2.0,
activeColor: Color.fromRGBO(88, 203, 143, 0.25),
inactiveColor: Color.fromRGBO(224, 233, 240, 0.50),
activeToggleColor: Color.fromRGBO(88, 203, 143, 1.0),
inactiveToggleColor: Color.fromRGBO(78, 88, 96, 0.50),
onToggle: (val) => setState(() {
_categoriesLinked[e.id] = val;
}),
),
SizedBox(width: _size.width * 0.01,),
Flexible(child: Text("${ e.id}. ${ e.name}"))
]
),
)
在这种情况下,您应该重构您的代码,以便将开关创建为另一个小部件,使它们只重建自己。
对于开关的状态,您可以简单地使用 GlobalKey<MySwitchState>
从父级获取它,以便在 onPressed
方法期间访问子级状态,例如:mySwitchKey.currentState
您绝对应该避免在方法内部构建有状态小部件。如果您觉得需要一种方法,请创建一个新的小部件。