Flutter:即使在来回切换屏幕后,如何仍将列表数据保留在表中? [英] Flutter: How to keep list data inside table even after switching screens back and forth?

查看:67
本文介绍了Flutter:即使在来回切换屏幕后,如何仍将列表数据保留在表中?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个用于CRUD的表格(第二个屏幕).当我添加数据时,如表所示,它会保存到列表视图.

列表视图被传递到(第一个屏幕),在这里我可以迭代并查看具有更新内容的列表数据.

但是,当我单击转到第二个屏幕时,列表视图数据消失了.给定的3个列表经过硬编码以用于测试目的.

现在,我的问题是,即使我多次来回切换屏幕,我如何也可以将数据保留在表中而不消失.我的代码如下:-

**

  1. Main.dart文件

**

  class MyApp扩展了StatefulWidget {@override_MyAppState createState()=>_MyAppState();}类别_MyAppState扩展了State< MyApp>{String _userInformation ='尚无信息';void languageInformation()异步{最终语言=等待Navigator.push(语境,MaterialPageRoute(生成器:(上下文)=>Episode5(),),);updateLanguageInformation(language);}void updateLanguageInformation(List< User> userList){for(var i = 0; i< = userList.length; i ++){对于(userList中的变量名){打印(名称:" + name.name [i] +电子邮件:" + name.email [i]);}}}@override窗口小部件build(BuildContext context){返回脚手架(appBar:AppBar(title:文本(从第二页到第一页的测试列表视图数据"),),正文:列(子代:< Widget> [柱子(crossAxisAlignment:CrossAxisAlignment.stretch,子代:< Widget> [文字(_userInformation),],),SizedBox(高度:10.0,),升高按钮(onPressed:(){languageInformation();},子代:文本("Go to Form"),),],),);}} 

2.Model.dart文件:

  class用户{字符串名称;字符串电子邮件;用户({this.name,this.email});} 

3.Episode5文件

  class Episode5扩展了StatefulWidget {@override_Episode5State createState()=>_Episode5State();}类_Episode5State扩展了状态< Episode5>.{TextEditingController nameController = TextEditingController();TextEditingController emailController = TextEditingController();最终形式= GlobalKey< FormState>();静态var _focusNode = new FocusNode();布尔更新=假;int currentIndex = 0;列出<用户>userList = [用户(名称:"a",电子邮件:"a"),用户(名称:"d",电子邮件:"b"),用户(名称:"c",电子邮件:"c"),];@override窗口小部件build(BuildContext context){窗口小部件bodyData()=>数据表onSelectAll:(b){},sortColumnIndex:0,sortAscending:是的,列:< DataColumn> [DataColumn(标签:Text(名称"),工具提示:要显示名称"),DataColumn(标签:Text("Email"),工具提示:"To Display Email"),DataColumn(标签:Text("Update"),工具提示:"Update data"),],行:userList.地图((用户)=>数据行(细胞: [数据单元文字(用户名),),数据单元文字(user.email),),数据单元IconButton(onPressed:(){currentIndex = userList.indexOf(user);_updateTextControllers(用户);//这里有新功能},图标:图标(Icons.edit,颜色:黑色.),),),],),).toList(),);返回脚手架(appBar:AppBar(标题:文本(使用表单将数据添加到列表中的数据"),),身体:容器(子:列(子代:< Widget> [bodyData(),填充(填充:EdgeInsets.all(10.0),子代:表格(关键:形式,子代:集装箱(子:列(子代:< Widget> [TextFormField(控制器:nameController,focusNode:_focusNode,keyboardType:TextInputType.text,自动更正:false,maxLines:1,验证者:(值){如果(value.isEmpty){返回此字段为必填项";}返回null;},装饰:新的InputDecoration(labelText:'名称',hintText:'名称',labelStyle:新的TextStyle(装饰样式:TextDecorationStyle.solid),),),SizedBox(高度:10,),TextFormField(控制器:emailController,keyboardType:TextInputType.text,自动更正:false,maxLines:1,验证者:(值){如果(value.isEmpty){返回此字段为必填项";}返回null;},装饰:新的InputDecoration(labelText:'电子邮件',hintText:'电子邮件',labelStyle:新的TextStyle(装饰样式:TextDecorationStyle.solid)),),SizedBox(高度:10,),柱子(子代:< Widget> [中心(子级:Row(crossAxisAlignment:CrossAxisAlignment.start,子代:< Widget> [排(crossAxisAlignment:CrossAxisAlignment.start,子代:< Widget> [TextButton(子代:文字("Add"),onPressed:(){form.currentState.save();addUserToList(nameController.text,emailController.text,);},),TextButton(子代:文本("Update"),onPressed:(){form.currentState.save();updateForm();},),],),排(crossAxisAlignment:CrossAxisAlignment.end,mainAxisAlignment:MainAxisAlignment.end,子代:< Widget> [升高按钮(子代:文字("Save and Exit"),onPressed:(){form.currentState.save();addUserToList(nameController.text,emailController.text,);Navigator.pop(context,userList);},),],),],),),],),],),),),),],),),);}void updateForm(){setState((){用户用户=用户(名称:nameController.text,电子邮件:emailController.text);userList [currentIndex] =用户;});}void _updateTextControllers(User user){setState((){nameController.text = user.name;emailController.text = user.email;});}void addUserToList(name,email){setState((){userList.add(User(name:name,email:email));});}} 

解决方案

因此,与其在页面之间来回传递数据,不如实施状态管理解决方案更好,这样您就可以从应用程序中的任何位置访问数据,而无需必须手动传递任何内容.

可以使用任何状态管理解决方案来完成此操作,这就是使用

I have a form (second screen) which is used for CRUD. When i add data, it is saved to list view as you can see on the table.

The list view is passed to (first screen) where i can iterate and see the list data with updated content.

However, when i click on go to second screen, the list view data disappears. The given 3 lists are hard coded for testing purpose.

Now, my question is that, How can i keep the data in the table and not disappear, even if i change screen back and forth multiple times. My code is as below: -

**

  1. Main.dart File

**

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  String _userInformation = 'No information yet';
  void languageInformation() async {
    final language = await Navigator.push(
      context,
      MaterialPageRoute(
        builder: (context) => Episode5(),
      ),
    );
    updateLanguageInformation(language);
  }

  void updateLanguageInformation(List<User> userList) {
    for (var i = 0; i <= userList.length; i++) {
      for (var name in userList) {
        print("Name: " + name.name[i] + " Email: " + name.email[i]);
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Testing List View Data From second page to first page"),
      ),
      body: Column(
        children: <Widget>[
          Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: <Widget>[
              Text(_userInformation),
            ],
          ),
          SizedBox(
            height: 10.0,
          ),
          ElevatedButton(
            onPressed: () {
              languageInformation();
            },
            child: Text("Go to Form"),
          ),
        ],
      ),
    );
  }
}

2. Model.dart File:

class User {
  String name;
  String email;

  User({this.name, this.email});
}

3. Episode5 File

class Episode5 extends StatefulWidget {
  @override
  _Episode5State createState() => _Episode5State();
}

class _Episode5State extends State<Episode5> {
  TextEditingController nameController = TextEditingController();
  TextEditingController emailController = TextEditingController();

  final form = GlobalKey<FormState>();
  static var _focusNode = new FocusNode();
  bool update = false;
  int currentIndex = 0;

  List<User> userList = [
    User(name: "a", email: "a"),
    User(name: "d", email: "b"),
    User(name: "c", email: "c"),
  ];

  @override
  Widget build(BuildContext context) {
    Widget bodyData() => DataTable(
          onSelectAll: (b) {},
          sortColumnIndex: 0,
          sortAscending: true,
          columns: <DataColumn>[
            DataColumn(label: Text("Name"), tooltip: "To Display name"),
            DataColumn(label: Text("Email"), tooltip: "To Display Email"),
            DataColumn(label: Text("Update"), tooltip: "Update data"),
          ],
          rows: userList
              .map(
                (user) => DataRow(
                  cells: [
                    DataCell(
                      Text(user.name),
                    ),
                    DataCell(
                      Text(user.email),
                    ),
                    DataCell(
                      IconButton(
                        onPressed: () {
                          currentIndex = userList.indexOf(user);
                          _updateTextControllers(user); // new function here
                        },
                        icon: Icon(
                          Icons.edit,
                          color: Colors.black,
                        ),
                      ),
                    ),
                  ],
                ),
              )
              .toList(),
        );

    return Scaffold(
      appBar: AppBar(
        title: Text("Data add to List Table using Form"),
      ),
      body: Container(
        child: Column(
          children: <Widget>[
            bodyData(),
            Padding(
              padding: EdgeInsets.all(10.0),
              child: Form(
                key: form,
                child: Container(
                  child: Column(
                    children: <Widget>[
                      TextFormField(
                        controller: nameController,
                        focusNode: _focusNode,
                        keyboardType: TextInputType.text,
                        autocorrect: false,
                        maxLines: 1,
                        validator: (value) {
                          if (value.isEmpty) {
                            return 'This field is required';
                          }
                          return null;
                        },
                        decoration: new InputDecoration(
                          labelText: 'Name',
                          hintText: 'Name',
                          labelStyle: new TextStyle(
                              decorationStyle: TextDecorationStyle.solid),
                        ),
                      ),
                      SizedBox(
                        height: 10,
                      ),
                      TextFormField(
                        controller: emailController,
                        keyboardType: TextInputType.text,
                        autocorrect: false,
                        maxLines: 1,
                        validator: (value) {
                          if (value.isEmpty) {
                            return 'This field is required';
                          }
                          return null;
                        },
                        decoration: new InputDecoration(
                            labelText: 'Email',
                            hintText: 'Email',
                            labelStyle: new TextStyle(
                                decorationStyle: TextDecorationStyle.solid)),
                      ),
                      SizedBox(
                        height: 10,
                      ),
                      Column(
                        children: <Widget>[
                          Center(
                            child: Row(
                              crossAxisAlignment: CrossAxisAlignment.start,
                              children: <Widget>[
                                Row(
                                  crossAxisAlignment: CrossAxisAlignment.start,
                                  children: <Widget>[
                                    TextButton(
                                      child: Text("Add"),
                                      onPressed: () {
                                        form.currentState.save();
                                        addUserToList(
                                          nameController.text,
                                          emailController.text,
                                        );
                                      },
                                    ),
                                    TextButton(
                                      child: Text("Update"),
                                      onPressed: () {
                                        form.currentState.save();
                                        updateForm();
                                      },
                                    ),
                                  ],
                                ),
                                Row(
                                  crossAxisAlignment: CrossAxisAlignment.end,
                                  mainAxisAlignment: MainAxisAlignment.end,
                                  children: <Widget>[
                                    ElevatedButton(
                                      child: Text("Save and Exit"),
                                      onPressed: () {
                                        form.currentState.save();
                                        addUserToList(
                                          nameController.text,
                                          emailController.text,
                                        );
                                        Navigator.pop(context, userList);
                                      },
                                    ),
                                  ],
                                ),
                              ],
                            ),
                          ),
                        ],
                      ),
                    ],
                  ),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }

  void updateForm() {
    setState(() {
      User user = User(name: nameController.text, email: emailController.text);
      userList[currentIndex] = user;
    });
  }

  void _updateTextControllers(User user) {
    setState(() {
      nameController.text = user.name;
      emailController.text = user.email;
    });
  }

  void addUserToList(name, email) {
    setState(() {
      userList.add(User(name: name, email: email));
    });
  }
}

解决方案

So instead of passing data back and forth between pages, its better to implement a state management solution so that you can access your data from anywhere in the app, without having to manually pass anything.

It can be done with any state management solution, here's how you could do it with GetX.

I took all your variables and methods and put them in a Getx class. Anything in this class will be accessible from anywhere in the app. I got rid of setState because that's no longer how things will be updated.

class FormController extends GetxController {
  TextEditingController nameController = TextEditingController();
  TextEditingController emailController = TextEditingController();
  int currentIndex = 0;

  List<User> userList = [
    User(name: "a", email: "a"),
    User(name: "d", email: "b"),
    User(name: "c", email: "c"),
  ];

  void updateForm() {
    User user = User(name: nameController.text, email: emailController.text);
    userList[currentIndex] = user;
    update();
  }

  void updateTextControllers(User user) {
    nameController.text = user.name;
    emailController.text = user.email;
    update();
  }

  void addUserToList(name, email) {
    userList.add(User(name: name, email: email));
    update();
  }

  void updateLanguageInformation() {
    // for (var i = 0; i <= userList.length; i++) { // ** don't need nested for loop here **
    for (var user in userList) {
      print("Name: " + user.name + " Email: " + user.email);
    }
    // }
  }
}

GetX controller can be initialized anywhere before you try to use it, but lets do it main.

void main() {
  Get.put(FormController()); // controller init
  runApp(MyApp());
}

Here's your page, we find the controller and now all variables and methods come from that controller.

class Episode5 extends StatefulWidget {
  @override
  _Episode5State createState() => _Episode5State();
}

class _Episode5State extends State<Episode5> {
  final form = GlobalKey<FormState>();
  static var _focusNode = new FocusNode();
  // finding same instance if initialized controller
  final controller = Get.find<FormController>();
  @override
  Widget build(BuildContext context) {
    Widget bodyData() => DataTable(
          onSelectAll: (b) {},
          sortColumnIndex: 0,
          sortAscending: true,
          columns: <DataColumn>[
            DataColumn(label: Text("Name"), tooltip: "To Display name"),
            DataColumn(label: Text("Email"), tooltip: "To Display Email"),
            DataColumn(label: Text("Update"), tooltip: "Update data"),
          ],
          rows: controller.userList // accessing list from Getx controller
              .map(
                (user) => DataRow(
                  cells: [
                    DataCell(
                      Text(user.name),
                    ),
                    DataCell(
                      Text(user.email),
                    ),
                    DataCell(
                      IconButton(
                        onPressed: () {
                          controller.currentIndex =
                              controller.userList.indexOf(user);
                          controller.updateTextControllers(user);
                        },
                        icon: Icon(
                          Icons.edit,
                          color: Colors.black,
                        ),
                      ),
                    ),
                  ],
                ),
              )
              .toList(),
        );

    return Scaffold(
      appBar: AppBar(
        title: Text("Data add to List Table using Form"),
      ),
      body: Container(
        child: Column(
          children: <Widget>[
            // GetBuilder rebuilds when update() is called
            GetBuilder<FormController>(
              builder: (controller) => bodyData(),
            ),
            Padding(
              padding: EdgeInsets.all(10.0),
              child: Form(
                key: form,
                child: Container(
                  child: Column(
                    children: <Widget>[
                      TextFormField(
                        controller: controller.nameController,
                        focusNode: _focusNode,
                        keyboardType: TextInputType.text,
                        autocorrect: false,
                        maxLines: 1,
                        validator: (value) {
                          if (value.isEmpty) {
                            return 'This field is required';
                          }
                          return null;
                        },
                        decoration: InputDecoration(
                          labelText: 'Name',
                          hintText: 'Name',
                          labelStyle: new TextStyle(
                              decorationStyle: TextDecorationStyle.solid),
                        ),
                      ),
                      SizedBox(
                        height: 10,
                      ),
                      TextFormField(
                        controller: controller.emailController,
                        keyboardType: TextInputType.text,
                        autocorrect: false,
                        maxLines: 1,
                        validator: (value) {
                          if (value.isEmpty) {
                            return 'This field is required';
                          }
                          return null;
                        },
                        decoration: InputDecoration(
                            labelText: 'Email',
                            hintText: 'Email',
                            labelStyle: new TextStyle(
                                decorationStyle: TextDecorationStyle.solid)),
                      ),
                      SizedBox(
                        height: 10,
                      ),
                      Column(
                        children: <Widget>[
                          Center(
                            child: Row(
                              crossAxisAlignment: CrossAxisAlignment.start,
                              children: <Widget>[
                                Row(
                                  crossAxisAlignment: CrossAxisAlignment.start,
                                  children: <Widget>[
                                    TextButton(
                                      child: Text("Add"),
                                      onPressed: () {
                                        form.currentState.save();
                                        controller.addUserToList(
                                          controller.nameController.text,
                                          controller.emailController.text,
                                        );
                                      },
                                    ),
                                    TextButton(
                                      child: Text("Update"),
                                      onPressed: () {
                                        form.currentState.save();
                                        controller.updateForm();
                                      },
                                    ),
                                  ],
                                ),
                                Row(
                                  crossAxisAlignment: CrossAxisAlignment.end,
                                  mainAxisAlignment: MainAxisAlignment.end,
                                  children: <Widget>[
                                    ElevatedButton(
                                      child: Text("Save and Exit"),
                                      onPressed: () {
                                        form.currentState.save();
                                        controller.updateLanguageInformation(); // all this function does is print the list
                                        Navigator.pop(
                                            context); // don't need to pass anything here
                                      },
                                    ),
                                  ],
                                ),
                              ],
                            ),
                          ),
                        ],
                      ),
                    ],
                  ),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

And here's your other page. I just threw in a ListView.builder wrapped in a GetBuilder<FormController> for demo purposes. It can now be stateless.

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Testing List View Data From second page to first page"),
      ),
      body: Column(
        children: <Widget>[
          Expanded(
            child: GetBuilder<FormController>(
              builder: (controller) => ListView.builder(
                itemCount: controller.userList.length,
                itemBuilder: (context, index) => Row(
                  mainAxisAlignment: MainAxisAlignment.spaceAround,
                  children: [
                    Text(controller.userList[index].name),
                    Text(controller.userList[index].email),
                  ],
                ),
              ),
            ),
          ),
          SizedBox(
            height: 10.0,
          ),
          ElevatedButton(
            onPressed: () {
              Navigator.push(
                context,
                MaterialPageRoute(
                  builder: (context) => Episode5(),
                ),
              );
            },
            child: Text("Go to Form"),
          ),
        ],
      ),
    );
  }
}

As your app expands you can create more controller classes and they're all very easily accessible from anywhere. Its a way easier and cleaner way to do things than manually passing data around everywhere.

这篇关于Flutter:即使在来回切换屏幕后,如何仍将列表数据保留在表中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆