https://www.bilibili.com/video/BV1U6421M7dw/
原文 https://ducafecat.com/blog/flutter-state-management-libraries-2024
状态管理是每个应用不可缺少的,本文将会盘点下主流的状态管理包。
对了 我还对插件包做了整理,欢迎移步查看 https://flutter.ducafecat.com .
轻量级、易学习、内置于Flutter中,适用于基本状态管理。
https://pub.dev/packages/provider
import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; /// This is a reimplementation of the default Flutter application using provider + [ChangeNotifier]. void main() { runApp( /// Providers are above [MyApp] instead of inside it, so that tests /// can use [MyApp] while mocking the providers MultiProvider( providers: [ ChangeNotifierProvider(create: (_) => Counter()), ], child: const MyApp(), ), ); } /// Mix-in [DiagnosticableTreeMixin] to have access to [debugFillProperties] for the devtool // ignore: prefer_mixin class Counter with ChangeNotifier, DiagnosticableTreeMixin { int _count = 0; int get count => _count; void increment() { _count++; notifyListeners(); } /// Makes `Counter` readable inside the devtools by listing all of its properties void debugFillProperties(DiagnosticPropertiesBuilder properties) { super.debugFillProperties(properties); properties.add(IntProperty('count', count)); } } class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); Widget build(BuildContext context) { return const MaterialApp( home: MyHomePage(), ); } } class MyHomePage extends StatelessWidget { const MyHomePage({Key? key}) : super(key: key); Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Example'), ), body: const Center( child: Column( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Text('You have pushed the button this many times:'), /// Extracted as a separate widget for performance optimization. /// As a separate widget, it will rebuild independently from [MyHomePage]. /// /// This is totally optional (and rarely needed). /// Similarly, we could also use [Consumer] or [Selector]. Count(), ], ), ), floatingActionButton: FloatingActionButton( key: const Key('increment_floatingActionButton'), /// Calls `context.read` instead of `context.watch` so that it does not rebuild /// when [Counter] changes. onPressed: () => context.read<Counter>().increment(), tooltip: 'Increment', child: const Icon(Icons.add), ), ); } } class Count extends StatelessWidget { const Count({Key? key}) : super(key: key); Widget build(BuildContext context) { return Text( /// Calls `context.watch` to make [Count] rebuild when [Counter] changes. '${context.watch<Counter>().count}', key: const Key('counterState'), style: Theme.of(context).textTheme.headlineMedium, ); } }
基于块模式构建,将业务逻辑与用户界面解耦,适用于复杂的状态管理。
https://pub.dev/packages/flutter_bloc
https://bloclibrary.dev/#/zh-cn/coreconcepts?id=bloc
https://bloclibrary.dev/#/zh-cn/gettingstarted
├── lib
│ ├── app.dart
│ ├── counter
│ │ ├── counter.dart
│ │ ├── cubit
│ │ │ └── counter_cubit.dart
│ │ └── view
│ │ ├── counter_page.dart
│ │ └── counter_view.dart
│ ├── counter_observer.dart
│ └── main.dart
├── pubspec.lock
├── pubspec.yaml
这个应用中我们使用的是功能驱动(feature-driven)的项目结构。
这种项目结构可以让我们通过一个个独立的功能来扩展项目。
适用于中大型应用程序的具有类型、作用域和关注点分离的改进版提供程序。
https://pub.dev/packages/riverpod
https://riverpod.dev/zh-hans/docs/introduction/getting_started
import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; part 'main.g.dart'; // 我们创建了一个 "provider",它可以存储一个值(这里是 "Hello world")。 // 通过使用提供者程序,这可以允许我们模拟或者覆盖一个暴露的值。 String helloWorld(HelloWorldRef ref) { return 'Hello world'; } void main() { runApp( // 为了使小组件可以读取提供者程序, // 我们需要将整个应用程序包装在“ProviderScope”小部件中。 // 这是我们的提供者程序的状态将被存储的地方。 ProviderScope( child: MyApp(), ), ); } // 继承父类使用 ConsumerWidget 替代 StatelessWidget,这样可以获取到提供者程序的引用 class MyApp extends ConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { final String value = ref.watch(helloWorldProvider); return MaterialApp( home: Scaffold( appBar: AppBar(title: const Text('Example')), body: Center( child: Text(value), ), ), ); } }
全能框架,用于状态管理、路由和依赖注入,非常适用于低到中等复杂度的应用程序。
订阅更新
void main() => runApp(MaterialApp(home: Home())); class Home extends StatelessWidget { var count = 0.obs; Widget build(context) => Scaffold( appBar: AppBar(title: Text("counter")), body: Center( child: Obx(() => Text("$count")), ), floatingActionButton: FloatingActionButton( child: Icon(Icons.add), onPressed: () => count ++, )); }
手动更新
Widget build(BuildContext context) { return GetBuilder<MatchIndexController>( init: MatchIndexController(fixtureId), id: "match_index", tag: tag, // 区分不同控制器 builder: (_) { return controller.fixturesInfo == null ? const ProgressIndicatorWidget().paddingTop(100) : _buildView(); }, ); }
_initData() async { await _loadData(); update(["match_index"]); }
https://github.com/jonataslaw/get_cli/blob/master/README-zh_CN.md
https://marketplace.visualstudio.com/items?itemName=ducafecat.getx-template
https://ducafecat.com/course/flutter-woo
MobX是一种状态管理库,它让应用程序的响应式数据与 UI 关联起来变得很简单。
https://pub.dev/packages/flutter_mobx
https://github.com/mobxjs/mobx.dart/tree/master/mobx_examples/lib/counter
import 'package:flutter/material.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:mobx/mobx.dart'; part 'counter.g.dart'; class Counter = CounterBase with _$Counter; abstract class CounterBase with Store { int value = 0; void increment() { value++; } } class CounterExample extends StatefulWidget { const CounterExample({Key key}) : super(key: key); _CounterExampleState createState() => _CounterExampleState(); } class _CounterExampleState extends State<CounterExample> { final _counter = Counter(); Widget build(BuildContext context) => Scaffold( appBar: AppBar( title: const Text('Counter'), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ const Text( 'You have pushed the button this many times:', ), Observer( builder: (_) => Text( '${_counter.value}', style: const TextStyle(fontSize: 20), )), ], ), ), floatingActionButton: FloatingActionButton( onPressed: _counter.increment, tooltip: 'Increment', child: const Icon(Icons.add), ), ); }
监视变化
import 'package:mobx/mobx.dart'; final greeting = Observable('Hello World'); final dispose = reaction((_) => greeting.value, (msg) => print(msg)); greeting.value = 'Hello MobX'; // Cause a change // Done with the reaction() dispose(); // Prints: // Hello MobX
具有集中式存储、操作和减速器的可预测状态管理,适用于需要强大可预测性和工具的应用程序。
https://pub.dev/packages/flutter_redux
import 'package:flutter/material.dart'; import 'package:flutter_redux/flutter_redux.dart'; import 'package:redux/redux.dart'; // One simple action: Increment enum Actions { Increment } // The reducer, which takes the previous count and increments it in response // to an Increment action. int counterReducer(int state, dynamic action) { return action == Actions.Increment ? state + 1 : state; } void main() { // Create your store as a final variable in the main function or inside a // State object. This works better with Hot Reload than creating it directly // in the `build` function. final store = Store<int>(counterReducer, initialState: 0); runApp(FlutterReduxApp( title: 'Flutter Redux Demo', store: store, )); } class FlutterReduxApp extends StatelessWidget { final Store<int> store; final String title; FlutterReduxApp({Key key, this.store, this.title}) : super(key: key); Widget build(BuildContext context) { // The StoreProvider should wrap your MaterialApp or WidgetsApp. This will // ensure all routes have access to the store. return StoreProvider<int>( // Pass the store to the StoreProvider. Any ancestor `StoreConnector` // Widgets will find and use this value as the `Store`. store: store, child: MaterialApp( theme: ThemeData.dark(), title: title, home: Scaffold( appBar: AppBar(title: Text(title)), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ // Connect the Store to a Text Widget that renders the current // count. // // We'll wrap the Text Widget in a `StoreConnector` Widget. The // `StoreConnector` will find the `Store` from the nearest // `StoreProvider` ancestor, convert it into a String of the // latest count, and pass that String to the `builder` function // as the `count`. // // Every time the button is tapped, an action is dispatched and // run through the reducer. After the reducer updates the state, // the Widget will be automatically rebuilt with the latest // count. No need to manually manage subscriptions or Streams! StoreConnector<int, String>( converter: (store) => store.state.toString(), builder: (context, count) { return Text( 'The button has been pushed this many times: $count', style: Theme.of(context).textTheme.display1, ); }, ) ], ), ), // Connect the Store to a FloatingActionButton. In this case, we'll // use the Store to build a callback that will dispatch an Increment // Action. // // Then, we'll pass this callback to the button's `onPressed` handler. floatingActionButton: StoreConnector<int, VoidCallback>( converter: (store) { // Return a `VoidCallback`, which is a fancy name for a function // with no parameters and no return value. // It only dispatches an Increment action. return () => store.dispatch(Actions.Increment); }, builder: (context, callback) { return FloatingActionButton( // Attach the `callback` to the `onPressed` attribute onPressed: callback, tooltip: 'Increment', child: Icon(Icons.add), ); }, ), ), ), ); } }
一个针对Flutter优化的Redux版本,减少样板代码,同时保持架构概念。
https://pub.dev/packages/fish_redux
这是一个依赖管理工具,当然也能用来作为简单的状态管理,比如全局、局部的数据维护。
https://pub.dev/packages/get_it
我专门做一个视频可以移步看下。
视频 https://www.bilibili.com/video/BV1EG411X7zz
文档 https://ducafecat.com/blog/use-get_it-in-getx
每个库都有其优点和缺点,适用于不同的应用程序大小和复杂性。对于基本应用程序,推荐使用Provider和GetX,而对于较大的应用程序,可以从BLoC/Cubit、Riverpod或MobX中受益。在选择库时,请考虑您的应用程序需求、团队偏好和架构风格。
总之,强大的状态管理对于应用的稳定性和增长至关重要。Flutter提供了一系列的库来满足不同的需求,确保稳定性、可测试性和可维护性。无论你是初创公司还是已经建立起来的企业,选择合适的状态管理库对于成功至关重要。
感谢阅读本文
如果有什么建议,请在评论中让我知道。我很乐意改进。
Flutter 优秀插件推荐 https://flutter.ducafecat.com
Flutter 基础篇1 - Dart 语言学习 https://ducafecat.com/course/dart-learn
Flutter 基础篇2 - 快速上手
Flutter 实战1 - Getx Woo 电商APP
Flutter 实战2 - 上架指南 Apple Store、Google Play https://ducafecat.com/course/flutter-upload-apple-google
Flutter 基础篇3 - 仿微信朋友圈 https://ducafecat.com/course/flutter-wechat
Flutter 实战3 - 腾讯 tim 即时通讯开发 https://ducafecat.com/course/flutter-tim
© 猫哥 ducafecat.com
end
Copyright 2024 ducafecat. All rights reserved.
微信: ducafecat, line: ducafecat,京ICP备2021009050号-3