状态管理
一. Provider
是对 InheritedWidget组件的上层封装 需要依赖于context上下文 更多详细

创建model类可以有多个属性,一个app可以有多个model类来存储数据
model类必须要继承ChangeNotifier类,否则无法刷新数据
model管理的状态,内部只有get方法,修改他的值是通过单独的方法进行修改的,在修改后要调用notifyListeners方法
model创建
import 'package:flutter/material.dart';class Counter with ChangeNotifier {int _count;Counter(this._count);void add() {_count++;notifyListeners();}get count => _count;}需要混入ChangeNotifier写一个增加的方法,然后需要调用notifyListeners();这个方法是通知用到Counter对象的widget刷新用的
导入(注入)model
void main() {runApp(ChangeNotifierProvider(create: (context) => Counter(1),child: MyApp(),));}
还有以下几个方法
Provider,ListenableProvider,ValueListenableProvider,StreamProvider,
如果是多个Provider
MultiProvider(providers: [ChangeNotifierProvider.value(value: UserInfo('','')),ChangeNotifierProvider.value(value: PageOne('','')),],child: Consumer2<UserInfo,PageOne>(builder: (context, login,user, _) {}))
获取值或改变Provider
需要导入对应model
获取Text("${Provider.of<Counter>(context).count}")改变Provider.of<Counter>(context).add();
Provider.of(context).count取值,Provider.of(context)相当于Provider去查找它管理的Counter(1)
用Provider.of(context).add();调用Counter()中的add()方法改变值
二. GetX
https://pub.dev/packages/get
优势点:
GetX 因为不需要上下文,突破了InheritedWidget的限制,我们可以在全局和模块间共享状态
AJAX数据请求到更新UI层
主要功能
- 状态管理
分别有两个状态管理器(GetBuilder)和响应式状态管理器(GetX)
响应式状态管理器
申明
var num = 0;
监听 num
var num = 0.obs;
UI层显示更新
Obx(() => Text(“${controller.num}”));
- 路由管理
不想要上下文的情况下使用
在main.dart文件下把MaterialApp替换变成GetMaterialApp
GetMaterialApp( // Before: MaterialApp(home: MyHome(),)
路由跳转
1.导航到新页面
Get.to(NextScreen());
2.用别名导航到新页面
Get.toNamed('/details');
3.要关闭snackbars, dialogs, bottomsheets或任何你通常会用Navigator.pop(context)关闭的东西。
Get.back();
4.进入下一个页面,但没有返回上一个页面的选项(用于闪屏页,登录页面等)。
Get.off(NextScreen());
5.进入下一个页面并取消之前的所有路由(在购物车、投票和测试中很有用)。
Get.offAll(NextScreen());
以上都不需要context上下文
- 依赖管理
Get有一个简单而强大的依赖管理器,它允许你只用1行代码就能检索到与你的Bloc或Controller相同的类,无需Provider context,无需inheritedWidget。
Controller controller = Get.put(Controller()); // 而不是 Controller controller = Controller(); 主任依赖
使用获取依赖
Controller controller = Get.find();
更多API移步 https://pub.flutter-io.cn/packages/get
项目示例
首先需要一个控制器
class nController extends GetxController {int _counter = 0;int get counter => _counter;void increment() {_counter++;update();}}
UI 层显示数字变化以及控制数字
class nPage extends StatelessWidget {@overrideWidget build(BuildContext context) {print('nPage--build');return GetBuilder<nController>(init: nController(), //初始化builder: (controller) {return Scaffold(appBar: AppBar(title: Text('数字变化..')),body: Center(child: Text(controller.counter.toString()),),floatingActionButton: FloatingActionButton(onPressed: () {controller.increment();},child: Icon(Icons.add),),);});}}
通过GetBuilder对 Widget 包裹了页面,在 init初始化nController,然后每次点击,都会更新builder对应的 Widget ,GetxController通过update()更新GetBuilder。
注:可以局部更新某个组件
以上代码改造
class nPage extends StatelessWidget {@overrideWidget build(BuildContext context) {print('nPage--build');return Scaffold(appBar: AppBar(title: Text('数字变化..')),body: Center(child: GetBuilder<nController>(init: nController(),builder: (controller) {return Text(controller.counter.toString());}),),floatingActionButton: FloatingActionButton(onPressed: () {controller.increment();},child: Icon(Icons.add),),);}}
以上情况在按钮事件会找不到controller(因为作用域的关于),此时GetX就发会了作用
Get.find<nController>().increment();
GetxController生命周期
@overridevoid onInit() {super.onInit();print('nController--onInit');}@overridevoid onReady() {super.onReady();print('nController--onReady');}@overridevoid onClose() {super.onClose();print('nController--onClose');}
局部刷新
只需要在GetBuilder对应的Controller里面添加id
update(['id值']);
响应式刷新
以上是通过Controller以流的方式发送数据,而GetX提供了.obs后缀形式更新某个小部件
var nmu = 0.obs;监听Obx (() => Text (controller.num));.obs就实现了一个被观察者
.obs就实现了一个被观察者,类型是 RxInt。对应的小部件也不再是GetBuilder了,而是下面两种
final nmb1 = 0.obs;final nmb2 = 0.obs;GetX<nController>(builder: (_) {print("nmb1 rebuild");return Text('${_.nmb1}',style: TextStyle(fontWeight: FontWeight.bold),);},),Obx(() => Text('${Get.find<nController>().nmb2}',style: TextStyle(fontWeight: FontWeight.bold),)),
以上是同一个页面兄弟组件跨组件使用
跨路由
在one路由get.put oneController
import 'package:flutter/material.dart';import 'package:get/get.dart';import 'package:fluttergetx/controller/OneController.dart';class OnePage extends StatelessWidget {@overrideWidget build(BuildContext context) {OneController controller = Get.put(OneController());return Scaffold(appBar: AppBar(title: Text("第一个页面"),centerTitle: true,),body: Container(width: double.infinity,child: Column(children: [Text('第一个页面'),ListTile(onTap: () {Get.toNamed('/twoPage');},title: Text('第二个页面'),),],)));}}
在two路由get.find oneController
import 'package:flutter/material.dart';import 'package:get/get.dart';import 'package:fluttergetx/controller/OneController.dart';class TwoPage extends StatelessWidget {var ages = Get.find<OneController>().show();@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text("第二个页面"),centerTitle: true,),body: Container(width: double.infinity,child: Column(children: [Text('第二个页面'),Text('第一个页面过来的值:${ages}'),RaisedButton(color: Colors.blue,child: Text('打印OneController的值',style: TextStyle(color: Colors.white),),// 设置按钮圆角shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5.0)),onPressed: () {print(Get.find<OneController>().show());}),],)));}}
GetBuilder vs GetX vs Obx
项目结构




