我有一个UserNotifier,它有一个user对象作为state,这个对象有一些属性,包括用户最喜欢的主题ID的列表.我还有另外一个TopicsAsyncNotifier,它的topic个对象的列表为state,但是,这个列表必须基于用户的Collection 主题ID创建,因此在TopicsNotifierProviderbuild方法中,我首先必须从存储库中加载主题,然后我必须让userNotifier实例读取用户主题ID,最后使用主题列表和用户主题ID创建一个新的Topic对象,该对象具有一个附加属性,该属性指示该主题是否出现在Collection 用户主题中,这是一种isSelected, isFavorite标志.让我来展示一下,以便更好地理解.

class FollowedTopicsNotifier extends AsyncNotifier<List<FollowableTopic>> {
  @override
  FutureOr<List<FollowableTopic>> build() async {
    final topics = await ref.watch(topicsRepository).fetchTopics();

    final user = ref.read(userNotifier);
  
    final followedTopics = topics.map(
      (topic) => FollowableTopic(
        topic: topic,
        isFollowed: user.followedTopics.contains(topic.id)
      )
    ).toList();

    return followedTopics;
  }

  void updateTopics(String topicId, bool isSelected) {
    ... // logic to update state
  }
}

我只需要在TopicsAsyncNotifier初始化时执行build方法,当用户将新主题添加到Collection 夹时,我将使用updateTopics方法更新主题列表.所以我的问题是:文档说使用ref.read in build方法是不好的做法,但是如果我使用ref.watchref.watch(provider.select)来检索用户主题ID的列表,当我向用户列表添加新主题时,TopicsAsyncNotifierbuild方法将再次被调用,我不希望这样,因为这会再次加载初始主题,并且我已经在状态中加载了它们,所以我如何才能只从UserNotifier读取一次值来初始化TopicsAsyncNotifier而不使用ref.watchref.watch(provider.select)呢?我想过使用一个ProviderScope来处理TopicsAsyncNotifier,并在他的构造函数中传递初始的用户主题ID,但我不知道这是不是一个好方法.

我希望得到任何关于如何实现所需行为的建议,或者可能是使用其他提供者数据初始化提供者而不会暂停更改的其他方法(无需参考观察).

非常感谢你的咀嚼!

推荐答案

有两点你可以试着重新考虑:

  1. 创建一层高速缓存的数据TopicsNotifier.这将允许您在其build方法中获取fetchTopics一次,然后每次都返回它们.然后它将看起来如下所示:
class FollowedTopicsNotifier extends AsyncNotifier<List<FollowableTopic>> {
  @override
  FutureOr<List<FollowableTopic>> build() async {
    final topics = ref.watch(topicsNotifierProvider);

    final user = ref.watch(userNotifier); // better use `userNotifier.select`
  
    final followedTopics = topics. ... // handle AsyncValue here
  }
}
  1. final user = ref.read(userNotifier);-你需要在这里使用ref.watch(userNotifier)ref.watch(userNotifier.select),因为你的FollowedTopicsNotifier清楚地和逻辑上依赖于userNotifier的数据,而userNotifier的数据显然会改变,所以你不能只读一次.这会 destruct 你的程序.

Flutter相关问答推荐

为什么Riverpod生成器在这种情况下不生成AsyncNotiator?

material 3芯片,不能go 除输入芯片小部件上的轮廓

如何知道当前屏幕是否处于抖动状态?

Flutter 隔离.使用多个参数运行

在Flutter 中更改扩展瓷砖的高度

从图标启动器打开时,VSCode未检测到Web设备

Flutter 中的 setState() 内部是如何工作的?

如何将小部件代码移动到另一个文件以获得更好的可读性

Flutter 需要 Xcode 14 或更高版本

如何在flutter中实现这样的底部导航栏?

如何将取消图标放置在右上角

无法将Null类型的值分配给 const 构造函数中List类型的参数

升级到 Flutter 3.10 后,Flutter 键盘填充不起作用. Flutter 3.10 如何防止 BottomSheet 被键盘覆盖?

如何与 PostgreSQL 和外部网站交互 flutter apk?

有什么办法可以消除Flutter 中的传递依赖?

flutter 中 // 和 /// 有什么区别

Android Electric eel Mac M1:运行 flutter doctor -v 时无法找到Bundle 的 java 版本

Flutter 中父容器顶部的 Gridview 间距额外区域

如何从用户 Flutter 导航抽屉中隐藏管理菜单

如何在Flutter 中专注于列表视图中最新添加的项目