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

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

【问题讨论】:

    标签: flutter design-patterns architecture google-cloud-firestore flutter-provider


    【解决方案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
    • 谢谢。我想我会考虑使用流来解决我的状态问题,也许会想出一个自定义的解决方案。我会接受你的回答,因为我的问题有点泛滥。我还发现了以下repovideo,我觉得这很有趣。
    • @Erlend 是的,github repo 展示了一个有趣的概念!我通常会建议至少在使用像 ObservableState 这样的抽象之前玩一下 vanilla 流/rxdart。我还将StreamControllerStreamSinkObservable 封装到我自己的自定义类中,这样它们就更容易用于我自己的用例了。
    • 刚开始使用流、dartrx 和 BehaviorSubject,结合 StreamBuilder,真是太好了!!
    【解决方案2】:

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

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

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

    【讨论】:

      猜你喜欢
      • 2021-04-11
      • 1970-01-01
      • 1970-01-01
      • 2019-11-16
      • 2021-10-01
      • 2020-05-02
      • 1970-01-01
      • 1970-01-01
      • 2019-03-03
      相关资源
      最近更新 更多