【问题标题】:Flutter riverpod automatic state change based on eventFlutter RiverPod 基于事件自动改变状态
【发布时间】:2021-03-16 16:45:51
【问题描述】:

我是 Riverpod 的新手,虽然这些文章对入门很有帮助,但我却在与陈旧的状态作斗争。

当用户登录时,我正在设置一些状态。当数据库中的状态细节发生变化时,我希望重建自动发生。虽然我能够从数据库获取流,但我无法将数据库更改连接到 Riverpod 状态。

该模式用于协作。两个用户在独立的手机、平板电脑等上使用应用程序的同一部分。

我正在使用来自 firecloudstore 的文档流和集合流。

任何有用的文章或您如何使用 Riverpod 解决这个问题?我是否必须为此花时间学习 BLoC 之类的东西?

【问题讨论】:

  • 取决于您使用的是哪个特定的 RiverPod 提供程序,但您希望在某处调用最终会触发 notifyListeners() 调用的方法。

标签: flutter streaming state-management riverpod


【解决方案1】:

你绝对不需要学习 BLoC 来完成你所追求的。

您说您正在使用 firebase 流,所以这里有一个在您的数据更改时实时重建的示例。

首先,您的存储库层。

class YourRepository {
  YourRepository(this._read);

  static final provider = Provider((ref) => YourRepository(ref.read));
  
  final Reader _read;

  Stream<YourModel?> streamById(String id) {
    final stream = FirebaseFirestore.instance.collection('YourCollection').doc(id).snapshots();
    return stream.map((event) => event.exists ? YourModel.fromJson(event.data()!) : null);
  }
}

接下来,定义一个 StreamProvider 来读取存储库中定义的流。

final streamYourModelById = StreamProvider.autoDispose.family<YourModel?, String>((ref, id) {
  return ref.watch(YourRepository.provider).streamById(id);
});

最后,使用小部件中的 StreamProvider 在数据更改时重新加载。

// Hooks
class YourWidget extends HookWidget {
  const YourWidget({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: useProvider(streamYourModelById('YourDataId')).when(
        loading: () => const Center(child: CircularProgressIndicator()),
        error: (err, stack) => Center(child: Text(err.toString())),
        data: (yourData) => Center(child: Text(yourData?.toString() ?? 'Got Null')),
      ),
    );
  }
}

// Without Hooks
class YourWidget extends ConsumerWidget {
  const YourWidget({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context, ScopedReader watch) {
    return Scaffold(
      body: watch(streamYourModelById('YourDataId')).when(
        loading: () => const Center(child: CircularProgressIndicator()),
        error: (err, stack) => Center(child: Text(err.toString())),
        data: (yourData) => Center(child: Text(yourData?.toString() ?? 'Got Null')),
      ),
    );
  }
}

您应该能够应用此模式来完成您需要的任何事情。

【讨论】:

  • 看起来我让它变得比必要的更复杂。感谢您的帮助。
猜你喜欢
  • 2022-09-27
  • 2021-02-10
  • 1970-01-01
  • 1970-01-01
  • 2021-01-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-24
相关资源
最近更新 更多