Riverpod 在热重新加载之前不会重新加载消费者小部件

时间:2021-07-07 19:36:17

标签: flutter riverpod

我无法让 Riverpod 通知状态更改。我是 Riverpod 的新手,所以我可能误解了它的工作原理。

我想使用 Riverpod 提供一个对象变量,我在另一个小部件树上设置信息,然后再将该类中的信息提供给单独的小部件树中的使用者。这个消费者在功能上充当一种窗口片段,我想在屏幕的这一部分放置一个特定的小部件,由提供的对象中的信息决定。

这是我为对象设置的提供者。

final userPageContext = StateProvider<UserPageContext>((ref) {
  return UserPageContext(ptContext: PageTypes.WELCOME);
});

这是我在显示特定小部件之前观察状态变化的消费者。

Consumer(
                builder: (context, ScopedReader watch, __) {
                  final pageContext = watch(userPageContext).state;
                  return getPageToDisplay(pageContext);
                },
              ),

此函数提供要显示的小部件。

  Widget getPageToDisplay(UserPageContext pageContext) {
    if (pageContext.entryReady) {
      return EntryScreen(entry: pageContext.getNewEntry());
    } else {
      return Container();
    }
  }

这是我更改所提供对象状态的构建方法。

@override
  Widget build(BuildContext context) {
    return Consumer(builder: (_, ScopedReader watch, __) {

      final pageContext = watch(userPageContext).state;

      return Dialog(
        ... widgets ...
                Row(
                  ... widgets ...
                        // A button press confirms the users choice and then submits it to the provider
                        onPressed: () {
                          Entry entry = Entry(
                              entryType: entryType,
                              id: id,
                              name: name);

                          pageContext.ptContext = PageTypes.ENTRY;
                          pageContext.setNewEntry(entry);
                          pageContext.entryReady = true;

                          // These pops remove dialog menus that were in the current widget branch
                          Navigator.of(context).pop();
                          Navigator.of(context).pop();
                        },
                        ... widgets ...
                        ),
                      ),
                    )
                  ],
                )
              ],
            ),
          ),
        ),
      );
    });
  }

这是用于存储状态信息的类。

class UserPageContext {
  UserPageContext({required this.ptContext});

  late Entry _newEntry;
  bool entryReady = false;

  /// sets new entry and flags the class state to ready for listeners
  void setNewEntry(Entry entry) {
    _newEntry = entry;
    entryReady = true;
  }

  Entry getNewEntry() {
    entryReady = false;
    return _newEntry;
  }

  PageTypes ptContext;
}

我尝试了许多不同的变体,我以这种方式调用提供者,从 context.read 和 watch 到 watch(object.notifier) 和 watch(object.notifier).state。我想我已经尝试了大部分可能性,所以我不确定这是否可能是我的问题的原因。

-- 小编辑-- 我忘了补充一点,继续执行逻辑似乎工作正常,但在我执行热重载之前状态不会更新。预期页面随即出现。但奇怪的是,页面在再次热加载后立即消失。这似乎表明我提供给提供者的信息在使用后立即被重写,或者我以某种方式没有改变提供者?老实说,我不确定。

预先感谢您,希望您有美好的一天!

1 个答案:

答案 0 :(得分:0)

我好像解决了这个问题。我再次尝试使用 ChangeNotifierProvider。将此与扩展的 ChangeNotifier 结合使用,并确保在适当的时间通知 NotifyListeners,似乎可以解决问题。

这是我最终使用的提供程序。

final userPageContext = ChangeNotifierProvider((ref) {
  return UserPageContext(ptContext: PageTypes.WELCOME);
});

这些是我对课程所做的更改。

class UserPageContext extends ChangeNotifier {

  /// sets new entry and flags the class state to ready for listeners
  void setNewEntry(Entry entry) {
    ... code ...
    notifyListeners();
  }
 ...

最后,我第一次尝试 ChangeNotifier 时遇到的一个问题是它似乎没有状态访问权限,类似于许多其他与 Riverpod 一起使用的提供程序的语法。事实证明您不需要那个,因为它只是在您观看时返回您正在寻找的对象。这是我致电提供商的方式。

final pageContext = watch(userPageContext);