Flutter:如何在来回切换屏幕后将列表数据保留在 table 内?

Flutter: How to keep list data inside table even after switching screens back and forth?

我有一个用于 CRUD 的表单(第二个屏幕)。当我添加数据时,它会保存到列表视图中,如您在 table.

中所见

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

但是,当我点击转到第二个屏幕时,列表视图数据消失了。出于测试目的,给定的 3 个列表是硬编码的。

现在,我的问题是,即使多次来回切换屏幕,我怎样才能将数据保存在 table 中而不消失。我的代码如下:-

**

  1. Main.dart 文件

**

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 文件:

class User {
  String name;
  String email;

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

3。第 5 集文件

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));
    });
  }
}

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

可以使用任何状态管理解决方案来完成,这里是您可以使用 GetX 来完成的方法。

我把你所有的变量和方法都放在了 Getx class 中。此 class 中的任何内容都可以从应用程序的任何位置访问。我摆脱了 setState 因为这不再是更新的方式。

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 控制器可以在您尝试使用它之前在任何地方进行初始化,但让我们主要进行初始化。

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

这是您的页面,我们找到了控制器,现在所有变量和方法都来自该控制器。

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
                                      },
                                    ),
                                  ],
                                ),
                              ],
                            ),
                          ),
                        ],
                      ),
                    ],
                  ),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

这是您的另一页。为了演示目的,我只是将 ListView.builder 包裹在 GetBuilder<FormController> 中。它现在可以是无状态的。

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"),
          ),
        ],
      ),
    );
  }
}

随着您的应用扩展,您可以创建更多控制器 class,而且它们都可以从任何地方轻松访问。与到处手动传递数据相比,这是一种更简单、更简洁的做事方式。