flutter setState()不更新UI元素,即使状态变量a Future已更新?

tkclm6bt  于 2023-01-21  发布在  Flutter
关注(0)|答案(1)|浏览(164)

我有一个HomePage屏幕,其中有一个FutureBuilder列表,用Future函数作为状态变量实现。我使用键访问Future,在另一个dart文件中更新Future。Future得到更新,我看到print语句时确信这一点,但当我调用setState方法时,UI不显示新添加的条目。
这是我的主页。dart:

class HomePage extends StatefulWidget {
  const HomePage({super.key});

  @override
  State<HomePage> createState() => HomePageState();
}

class HomePageState extends State<HomePage> {
  Future<List<Model>> getData() async {
    return await DatabaseHelper.instance.getModels();
  }

  Future? userFuture;

  @override
  void initState() {
    super.initState();
    userFuture = getData();
    print(userFuture);
  }

  @override
  Widget build(BuildContext context) {
    print('Building listview');
    return Center(
      child: FutureBuilder<List<Model>>(
        future: userFuture as Future<List<Model>>,
        builder: ((context, AsyncSnapshot<List<Model>> snapshot) {
          switch (snapshot.connectionState) {
            case ConnectionState.waiting:
              return const CircularProgressIndicator();
            default:
              if (snapshot.data!.isEmpty) {
                return Text('No data present');
              } else if (snapshot.hasData) {
                return ListView.builder(
                  itemCount: snapshot.data?.length,
                  itemBuilder: ((context, index) {
                    return MyCard(
                        key: ValueKey(snapshot.data![index].id),
                        snapshot.data![index].id,
                        snapshot.data![index].title,
                        snapshot.data![index].purpose);
                  }),
                );
              }
              return Text('data');
          }
        }),
      ),
    );
  }
}

这是我的另一个dart文件,在AddEntryState下我更新Future状态变量,然后在调用setState方法之后。

class RootPage extends StatefulWidget {
  const RootPage({super.key});

  @override
  State<RootPage> createState() => RootPageState();
}

class RootPageState extends State<RootPage> {
  static final GlobalKey<HomePageState> homepageKey =
      GlobalKey<HomePageState>();
  int currentPage = 0;
  List<Widget>? pages;

  @override
  void initState() {
    super.initState();
    pages = [
      HomePage(key: homepageKey),
      StatsPage(),
    ];
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('App Title'),
      ),
      body: pages?[currentPage],
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          Navigator.push(
              context, MaterialPageRoute(builder: (context) => AddEntry()));
        },
        child: Icon(Icons.add),
      ),
      bottomNavigationBar: NavigationBar(
        destinations: [
          NavigationDestination(icon: Icon(Icons.home), label: 'Home'),
          NavigationDestination(icon: Icon(Icons.data_usage), label: 'Stats'),
        ],
        onDestinationSelected: (int index) {
          setState(() {
            currentPage = index;
            print(index);
          });
        },
        selectedIndex: currentPage,
      ),
    );
  }
}

class AddEntry extends StatefulWidget {
  const AddEntry({super.key});

  @override
  State<AddEntry> createState() => _AddEntryState();
}

class _AddEntryState extends State<AddEntry> {
  final GlobalKey<FormState> _key = GlobalKey<FormState>();
  Map<String, String?> formField = <String, String?>{};

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('New Entry'),
      ),
      body: Form(
        key: _key,
        child: Column(
          children: [
            Flexible(
              child: MyTextField('Title', callback),
            ),
            Flexible(
              child: MyTextField('Purpose', callback),
            ),
            Flexible(
              child: MyTextField('Password', callback, obscure: true),
            ),
            TextButton(
              onPressed: () async {
                if (_key.currentState!.validate()) {
                  _key.currentState?.save();
                  formField.forEach((label, value) => print('$label = $value'));
                  await DatabaseHelper.instance.insertModel(Model(
                      id: null,
                      title: formField['Title'],
                      purpose: formField['Purpose'],
                      lastAccess: DateTime.now().toString(),
                      dateAdded: DateTime.now().toString(),
                      password: formField['Password']));
                  print(await DatabaseHelper.instance.getModels());
                  // await DatabaseHelper.instance.deleteAllData();
                  // print(await DatabaseHelper.instance.getModels());
                  ScaffoldMessenger.of(context).showSnackBar(
                    SnackBar(
                      content: Text('Data Saved!'),
                      action: SnackBarAction(
                        label: 'Edit',
                        onPressed: () {
                          print('edit pressed!');
                        },
                      ),
                    ),
                  );
                  Navigator.pop(context);
                  print("HomePage userFuture: ");
                  print(RootPageState.homepageKey.currentState!.userFuture!
                      .then((result) => print(result)));
                  print("getData function: ");
                  print(RootPageState.homepageKey.currentState!
                      .getData()
                      .then((result) => print(result)));

                  print("New Future: ");
                  print(RootPageState.homepageKey.currentState!.userFuture!
                      .then((result) => print(result)));

                  setState(() {
                    RootPageState.homepageKey.currentState!.userFuture =
                        RootPageState.homepageKey.currentState!.getData();
                  });

                  //add logic to rebuild home screen after every addition of entry
                }
              },
              child: Text('Submit'),
            ),
          ],
        ),
      ),
    );
  }

  callback(varLabel, varValue) {
    formField[varLabel] = varValue;
  }
}
r6l8ljro

r6l8ljro1#

问题是您正在更新AddEntryState中Future对象的状态,但是HomePage小部件没有重新构建以反映Future中的更改。解决此问题的一种方法是向AddEntry小部件传递回调函数,该函数在表单提交时更新HomePage小部件的状态。在HomePage小部件中,您可以将一个更新Future对象的回调函数传递给AddEntry小部件,并在AddEntry小部件的提交按钮的onPressed回调函数中调用该函数。Future对象将被更新,并且HomePage小部件将被重建以反映Future中的变化。

相关问题