flutter:自定义 InheritedProvider 实现状态管理

基于InheritedWidget,实现简单的数据驱动模型,模型结构如下:


图一.png
1. 数据存储

使用 InheritedWidget,新建 InheritedProvider

import 'package:flutter/material.dart';
class InheritedProvider extends InheritedWidget {
  final T data;
  InheritedProvider({@required this.data, Widget child}) : super(child: child);

  @override
  bool updateShouldNotify(InheritedProvider oldWidget) {
    //在此简单返回true,则每次更新都会调用依赖其的子孙节点的 didChangeDependencies
    return true;
  }
}
2. 变更通知

使用flutter自带的 ChangeNotifier 组件,封装工具类 ChangeNotifierProvider 用于响应数据变更,触发UI更新。

class ChangeNotifierProvider extends StatefulWidget {
  final Widget child;
  final T data; //共享的数据模型,要求继承ChangeNotifier

  const ChangeNotifierProvider({
    Key key,
    this.child,
    this.data,
  }) : super(key: key);

  ///提供方法,子树获取共享数据
  static T of(BuildContext context) {
    final provider =
        context.dependOnInheritedWidgetOfExactType>();
    return provider.data;
  }

  @override
  _ChangeNotifierProviderState createState() =>
      _ChangeNotifierProviderState();
}

class _ChangeNotifierProviderState
    extends State> {
  ///如果数据发生变化(model类调用 notifyListeners),重新构建InheritedProvider
  void update() {
    setState(() => {});
  }

  @override
  void didUpdateWidget(ChangeNotifierProvider 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(
      data: widget.data,
      child: widget.child,
    );
  }
}

原理:使用InheritedWidget作为父节点,当数据源更新时,数据模型经过ChangeNotifier的关联,触发 _ChangeNotifierProviderState 的 setState方法,刷新UI。

封装 NotifyConsumer

直接显式调用 ChangeNotifierProvider.of 获取共享数据语义不明确,我们将其做一层简单的封装用于子节点获取数据:

///响应数据变化的消费者
class NotifyConsumer 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(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 {
  @override
  Widget build(BuildContext context) {
    return Center(
        child: ChangeNotifierProvider(
            data: CountModel(),
            child: Builder(builder: (context) {
              return Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Builder(
                    builder: (context) {
                      //获取共享数据源
                      return NotifyConsumer(
                          builder: (context, value) {
                        return Text(value.count.toString());
                      });
                    },
                  ),
                  Builder(builder: (context) {
                    return RaisedButton(
                      child: Text('自增'),
                      onPressed: () {
                        //获取共享model,进行数据自增操作
                        ChangeNotifierProvider.of(context).increase();
                      },
                    );
                  }),
                ],
              );
            })));
  }
}

你可能感兴趣的:(flutter:自定义 InheritedProvider 实现状态管理)