setState 在 ConsumerStatefulWidget (Riverpod) 中未按预期工作

问题描述 投票:0回答:1

我有一个自定义的 appbar 类,我将标题作为其构造函数传递。

class MyAppBar extends StatelessWidget implements PreferredSizeWidget {
  final String? title;
  @override
  Size get preferredSize => Size.fromHeight(AppBar().preferredSize.height);

  const MyAppBar({super.key, this.title});

  @override
  Widget build(BuildContext context) {
    return AppBar(title: Text(title ?? "CFlytics"));
  }
}

现在,我在 ConsumerStatefulWidget 中使用 MyAppBar,并将“appbartitle”作为传递给它的状态变量。

当我使用 setState 更新 appbartitle 变量时,它根本不会更新 appbar 标题

class _MyHomePageState extends State<MyHomePage> {
  String? appbartitle;

  @override
  Widget build(BuildContext context) {
    final myData =ref.watch(someProvider);
    return Scaffold(
      appBar: MyAppBar(title: appbartitle),

      body: myData.when(
          data: (data) {
            setState(() {appbartitle = "123";});
            return ...;
          },

          loading: {return ...}
          error:  {return ...}

但是当我将 setState 行包装在 Future.delayed 中时,即使延迟为 0 毫秒,它也会按要求工作

            Future.delayed(const Duration(milliseconds: 0), () {
              setState(() {appbartitle = "new title";});
            });

为什么会这样?实施这个的正确方法是什么?

flutter riverpod state-management mobile-development flutter-appbar
1个回答
0
投票

首先,这个语法看起来像旧的 Riverpod,从这个意义上说, someprovider 将是一个 FutureProvider 。尽管如此,如果您这样做,我希望看到错误“在构建期间调用 setstate 或 markNeedsBuild()”。我认为它不起作用,因为您在 myData.when() 中调用 setstate ,它也有效地调用 setstate ,所有这些都在同一个同步进程中。 将其放置在 Future.delayed 中使其成为异步调用,该调用在事件循环中的同步任务之后进行调度。您可以在 Flutter 中查找事件队列、微任务队列和异步进程。 通过将其包装在 Future 中,您只需在 myData.when 处理完它自己的 setstate 后调用 setstate 即可。 Riverpod 有 ref.listen,这是在构建中使用来更新数据的更合适的方法。 或者,我会写这样的东西,以免更改太多代码。

@override
Widget build(BuildContext context) {
final myData =ref.watch(someProvider);
if(myData.hasValue){
 appBarTitle = '123';
}
return Scaffold(
  appBar: MyAppBar(title: appbartitle),

  body: myData.when(
      data: (data) {
       //don't call setstate here
        return ...;
      },
      loading: {return ...},
      error:  {return ...},),
  );
 }

尽管如此,您仍然需要处理加载和错误状态,并且当状态处于加载/错误状态时 myData.haveValue 可以为 true。

© www.soinside.com 2019 - 2024. All rights reserved.