日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

flutter自定義InheritedProvider實現狀態管理詳解_Android

作者:李小轟_Rex ? 更新時間: 2022-12-12 編程語言

InheritedWidget簡單數據驅動模型

基于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();
                      },
                    );
                  }),
                ],
              );
            })));
  }
}

原文鏈接:https://juejin.cn/post/7007676764138766344#heading-3

欄目分類
最近更新