Flutter 中的多页面状态处理

Posted

技术标签:

【中文标题】Flutter 中的多页面状态处理【英文标题】:State handeling in Flutter with multiple pages 【发布时间】:2020-03-17 20:14:15 【问题描述】:

我正在尝试找出一种构建 Flutter 应用程序的好方法。我有几个页面,可以导航到其他页面。一页修改的数据,可能会被其他页使用,需要更新。我最近开始使用 Provider 包。我让每个页面都有一个实现 ChangeNotifier 的模型,并在 MaterialApp 上方设置了一个 ChangeNotifierProvider。现在要更新其他页面的数据,我必须获取其他页面的模型并在其上调用更新方法。这很乱。我使用 Firestore,所以我可以监听数据库的变化,但我想避免太多的魔法。此外,有时只将数据从一个页面发送到另一个页面而不使用网络调用,或者在 Navigator.pop 方法中将数据传回是有意义的。我发现很难在如何解决这个问题上做出好的选择。我可能应该看看更精致的架构,比如 redux 或 mobx。或者只是选择一个普通的解决方案,并为所有各种事件使用大量回调。每页那些big'ol模型,一段时间后似乎有点臃肿和凌乱。有没有人在 Flutter 方面有类似的经验如何构建这些东西? 困惑

【问题讨论】:

【参考方案1】:

使用provider 应用BLoC 模式并将其与RxDart 结合是解决此问题的一种方法。

例如,您可以创建一个AppBloc

class AppBloc 
  StreamController<UserInputState> _userInputController =
    BehaviorSubject<UserInputState>.seeded(UserInputState('NOTHING'));
  StreamSink<UserInputState> get userInputSink => _userInputController.sink;
  Observable<UserInputState> get userInputObs => Observable(_userInputController.stream);

  AppBloc();


class UserInputState 
  final String input;

  const UserInputState(this.input);

在一个页面上你可以通过它传递数据:

final appBloc = Provider.of<AppBloc>(context);
appBloc.userInputSink.add(UserInputState("input"));

另外一个页面可以监听数据:

final appBloc = Provider.of<AppBloc>(context);
appBloc.userInputObs.
    .where((state) => state.input == "input")
    .listen((state) => /* do something */);

我在这里对其进行了简化,但是这种可以是一种以反应方式处理数据的非常健壮的方式。

美妙之处在于您可以将Observable 绑定到StreamBuilder(Flutter 的一部分)以使 UI 也具有响应性!

【讨论】:

为什么需要 Observable?难道你不能只获得其他人可以收听的广播流吗? @Erlend 一个Observable 是一个使用类固醇的Stream。它只是扩展了Stream 并添加了许多有用的功能。更多详情请见here。 谢谢。我想我会考虑使用流来解决我的状态问题,也许会想出一个自定义的解决方案。我会接受你的回答,因为我的问题有点泛滥。我还发现了以下repo 和video,我觉得这很有趣。 @Erlend 是的,github repo 展示了一个有趣的概念!我通常会建议至少在使用像 ObservableState 这样的抽象之前玩一下 vanilla 流/rxdart。我还将StreamControllerStreamSinkObservable 封装到我自己的自定义类中,这样它们就更容易用于我自己的用例了。 刚开始使用流、dartrx 和 BehaviorSubject,结合 StreamBuilder,真是太好了!!【参考方案2】:

使用 Provider(或任何实现 BloC 模式的库)和存储库模式应该可以在本地移动/存储数据。基本上,每个 Bloc/Provider 都会获取存储库的一个实例并对其进行读/写值。由于存储库实例始终相同,因此您将更新所有数据。

此外,您可以使用本地数据库,例如 SQLite(带有 sqflite 包)或纯 NoSQL 数据库的 Hive。

我个人不喜欢 Redux,但 mobx 是一个非常好的选择。

【讨论】:

以上是关于Flutter 中的多页面状态处理的主要内容,如果未能解决你的问题,请参考以下文章

如何仅在 Flutter 中的特定页面上更改状态栏颜色

Flutter:何时创建无状态或有状态页面?

Flutter:未处理的异常:错误状态:DocumentSnapshotPlatform中不存在字段

flutter:根据不同的状态路由到不同的页面

Flutter 的 iOS 构建更新为 TestFlight 但在 Activity 会话中的“处理”状态后消失

Flutter StatefulWidget 有状态组件页面上绑定数据改变页面数据