flutter自定义InheritedProvider实现状态管理详解
李小轰_Rex 人气:0InheritedWidget简单数据驱动模型
基于InheritedWidget,实现简单的数据驱动模型,模型结构如下:
1. 数据存储
使用 InheritedWidget,新建 InheritedProvider
import 'package:flutter/material.dart'; class InheritedProvider<T> extends InheritedWidget { final T data; InheritedProvider({@required this.data, Widget child}) : super(child: child); @override bool updateShouldNotify(InheritedProvider<T> oldWidget) { //在此简单返回true,则每次更新都会调用依赖其的子孙节点的 didChangeDependencies return true; } }
2. 变更通知
使用flutter自带的 ChangeNotifier 组件,封装工具类 ChangeNotifierProvider 用于响应数据变更,触发UI更新。
class ChangeNotifierProvider<T extends ChangeNotifier> extends StatefulWidget { final Widget child; final T data; //共享的数据模型,要求继承ChangeNotifier const ChangeNotifierProvider({ Key key, this.child, this.data, }) : super(key: key); ///提供方法,子树获取共享数据 static T of<T>(BuildContext context) { final provider = context.dependOnInheritedWidgetOfExactType<InheritedProvider<T>>(); return provider.data; } @override _ChangeNotifierProviderState createState() => _ChangeNotifierProviderState<T>(); } class _ChangeNotifierProviderState<T extends ChangeNotifier> extends State<ChangeNotifierProvider<T>> { ///如果数据发生变化(model类调用 notifyListeners),重新构建InheritedProvider void update() { setState(() => {}); } @override void didUpdateWidget(ChangeNotifierProvider<T> oldWidget) { ///当Provider更新时,如果新旧数据不"==",则解绑旧数据监听,同时添加新数据监听 if (widget.data != oldWidget.data) { oldWidget.data.removeListener(update); widget.data.addListener(update); } super.didUpdateWidget(oldWidget); } @override void initState() { widget.data.addListener(update); super.initState(); } @override void dispose() { widget.data.removeListener(update); super.dispose(); } @override Widget build(BuildContext context) { return InheritedProvider<T>( data: widget.data, child: widget.child, ); } }
原理:使用InheritedWidget作为父节点,当数据源更新时,数据模型经过ChangeNotifier的关联,触发 _ChangeNotifierProviderState 的 setState方法,刷新UI。
封装 NotifyConsumer 直接显式调用 ChangeNotifierProvider.of
获取共享数据语义不明确,我们将其做一层简单的封装用于子节点获取数据:
///响应数据变化的消费者 class NotifyConsumer<T> extends StatelessWidget { final Widget Function(BuildContext context, T value) builder; const NotifyConsumer({Key key, @required this.builder}) : super(key: key); @override Widget build(BuildContext context) { return builder( context, ChangeNotifierProvider.of<T>(context), ); } }
3. 使用方法
创建一个共享数据模型:
///共享数据模型 class CountModel extends ChangeNotifier { int _count = 0; int get count => _count; //提供自增方法 void increase() { _count++; // 通知监听器(订阅者),重新构建InheritedProvider, 更新状态。 notifyListeners(); } }
ChangeNotifierProvider 的使用方式:
import 'package:flutter/material.dart'; import 'package:test_interited/provider/change_notifier_provider.dart'; import 'package:test_interited/provider/notify_consumer.dart'; import 'package:test_interited/provider/test/count_model.dart'; class TestNotifierWidget extends StatefulWidget { const TestNotifierWidget({Key key}) : super(key: key); @override _TestNotifierWidgetState createState() => _TestNotifierWidgetState(); } class _TestNotifierWidgetState extends State<TestNotifierWidget> { @override Widget build(BuildContext context) { return Center( child: ChangeNotifierProvider<CountModel>( data: CountModel(), child: Builder(builder: (context) { return Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Builder( builder: (context) { //获取共享数据源 return NotifyConsumer<CountModel>( builder: (context, value) { return Text(value.count.toString()); }); }, ), Builder(builder: (context) { return RaisedButton( child: Text('自增'), onPressed: () { //获取共享model,进行数据自增操作 ChangeNotifierProvider.of<CountModel>(context).increase(); }, ); }), ], ); }))); } }
加载全部内容