Flutter类间传值问题:传递值时另一值被重置
解决AddAd类中Region和Category传值互相重置的问题
我明白你的问题了——每次从Regions选择区域后,AddAd里的分类就变回初始值,反过来选分类后区域也重置。这是因为你在跳转时没有把当前已选择的另一个值传递过去,导致每次都是用新页面里的初始空值来构建AddAd。
问题根源
比如在Regions类里,你定义的sCategory是类内部的局部变量,初始值是空的,所以当你选择区域后跳转到AddAd时,传递的sCategory是这个空值,而不是AddAd里之前已经选好的分类。同理,Categories类里的sRegion也是空的,跳转时会覆盖掉AddAd里已有的区域值。
解决方案
核心思路是:在跳转到Regions/Categories页面时,把AddAd当前已有的Region和Category值传过去,这样在选择完新值后,就能带着两个完整的值回到AddAd,不会丢失之前的选择。
步骤1:修改Regions类的构造函数,接收外部传入的现有值
class Regions extends StatefulWidget { // 接收来自AddAd的当前已选值 final String existingRegion; final String existingCategory; Regions(this.existingRegion, this.existingCategory, {Key key}) : super(key: key); @override _RegionsState createState() => _RegionsState(); } class _RegionsState extends State<Regions> { String sRegion; String sCategory; @override void initState() { super.initState(); // 初始化时使用传入的现有值 sRegion = widget.existingRegion; sCategory = widget.existingCategory; } @override Widget build(BuildContext context) { return Directionality( textDirection: TextDirection.rtl, child: Scaffold( appBar: AppBar( title: Text("Location"), actions: <Widget>[ FlatButton( child: Text('Cancel', style: TextStyle(color: Colors.white),), onPressed: (){ // 取消时也带回现有值 Navigator.pushReplacement(context, MaterialPageRoute(builder: (context)=>AddAd(sRegion, sCategory))); }, ) ], ), body: SingleChildScrollView( child: Padding( padding: const EdgeInsets.only(top:15.0), child: Container( child: Column( children: <Widget>[ for(var item in regions) FlatButton( child: Text(item), onPressed: (){ sRegion = item; // 跳转时同时传递已有的category值 Navigator.push(context, new MaterialPageRoute(builder: (context) => AddAd(sRegion, sCategory))); print(sRegion); }, ), Divider(), ], ), ), ), ), ), ); } }
步骤2:修改AddAd类中跳转到Regions/Categories的逻辑
在AddAd的State类里用局部变量保存当前选择的值,同时给ListTile添加跳转事件,传递当前完整的状态:
class _AddAdState extends State<AddAd> { // 用局部变量保存当前选择的值,方便修改和传递 String currentRegion; String currentCategory; @override void initState() { super.initState(); // 初始化时使用widget传入的值 currentRegion = widget.sRegion; currentCategory = widget.sCategory; } @override Widget build(BuildContext context) { return Scaffold( // ... 其他原有代码 body: Column( children: [ ListTile( title: Text("Location"), subtitle: currentRegion == null ? Text("Where exactly") : Text(currentRegion), // 点击跳转到Regions,传递当前已选的两个值 onTap: () { Navigator.push(context, MaterialPageRoute( builder: (context) => Regions(currentRegion, currentCategory) )); }, ), ListTile( title: Text("Category"), subtitle: currentCategory == null ? Text("Department") : Text(currentCategory), // 点击跳转到Categories,传递当前已选的两个值 onTap: () { Navigator.push(context, MaterialPageRoute( builder: (context) => Categories(currentRegion, currentCategory) )); }, ), // ... 其他组件 ], ), ); } }
步骤3:Categories类做和Regions类一致的修改
Categories类的结构和Regions完全对应,只需要把变量名换成分类相关的:
class Categories extends StatefulWidget { final String existingRegion; final String existingCategory; Categories(this.existingRegion, this.existingCategory, {Key key}) : super(key: key); @override _CategoriesState createState() => _CategoriesState(); } class _CategoriesState extends State<Categories> { String sRegion; String sCategory; @override void initState() { super.initState(); sRegion = widget.existingRegion; sCategory = widget.existingCategory; } @override Widget build(BuildContext context) { return Directionality( textDirection: TextDirection.rtl, child: Scaffold( appBar: AppBar( title: Text("Category"), actions: <Widget>[ FlatButton( child: Text('Cancel', style: TextStyle(color: Colors.white),), onPressed: (){ Navigator.pushReplacement(context, MaterialPageRoute(builder: (context)=>AddAd(sRegion, sCategory))); }, ) ], ), body: SingleChildScrollView( child: Padding( padding: const EdgeInsets.only(top:15.0), child: Container( child: Column( children: <Widget>[ for(var item in categories) // 替换成你的分类列表 FlatButton( child: Text(item), onPressed: (){ sCategory = item; // 跳转时传递已有的region值 Navigator.push(context, new MaterialPageRoute(builder: (context) => AddAd(sRegion, sCategory))); print(sCategory); }, ), Divider(), ], ), ), ), ), ), ); } }
为什么这样能解决问题?
现在每次跳转到Regions或Categories时,都会把AddAd当前已选的两个值传递过去,选择新值后,再把新值+原有值一起传回AddAd,这样两个值就不会互相覆盖重置了。另外用State类的局部变量保存状态,比直接使用widget的不可变属性更灵活。
内容的提问来源于stack exchange,提问作者Alex Ali
相关产品推荐
相关产品推荐

