在应用开发过程中数据传递,flutter提供 InheritedWidget 以及多种 provider, 各有差异从从使用习惯上面 这边主要介绍以下两种:
- InheritedWidget
- provider (ChangeNotifier)
提供一种 从上而下 的数据提供 (而且子节点需要 Widget 包裹); 且单向。切记只能由上而下的刷新数据;不能做到 子节点 变数据 而刷新的情况!常用于 静态数据的存储;不会改变的常量保存; 或者子节点只作为 静态展示的数据,父节点提供元数据。子节点展示数据 不参与动态更新交互
效果如下:
脚本结构:
inherited_datum.dart
import 'package:flutter/cupertino.dart';class InheritedDatum extends InheritedWidget {final int count;const InheritedDatum({Key? key, required child, required this.count}): super(key: key, child: child);static InheritedDatum? of(BuildContext context) {return context.dependOnInheritedWidgetOfExactType
();}///**子组件不能 通过调用该方法 实现子组件刷新updateCount(int count) {count = count;}@overridebool updateShouldNotify(covariant InheritedDatum oldWidget) {// TODO: implement updateShouldNotifyreturn oldWidget.count != count;} } widget_child0.dart
import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart';import 'inherited_datum.dart';class WidgetChild0 extends StatelessWidget {const WidgetChild0({Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {return Container(color: Colors.blue,height: 40,width: 80,child: Center(child: Text('${InheritedDatum.of(context)?.count}',style: TextStyle(color: Colors.white),),),);} }
widget_child1.dart
import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart';import 'inherited_datum.dart';class WidgetChild1 extends StatelessWidget {const WidgetChild1({Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {return Container(color: Colors.blue,height: 40,width: 80,child: Center(child: Text('${InheritedDatum.of(context)?.count}',style: TextStyle(color: Colors.white),),),);} }
入口:main.dart
@override Widget build(BuildContext context) {return Scaffold(appBar: AppBar(// Here we take the value from the MyHomePage object that was created by// the App.build method, and use it to set our appbar title.title: Text(widget.title),),body: Center(child: InheritedDatum(count: _counter,child: Row(mainAxisAlignment: MainAxisAlignment.spaceAround,// children: const [],children: const [WidgetChild0(), WidgetChild1()],),),),floatingActionButton: FloatingActionButton(onPressed: _incrementCounter,tooltip: 'Increment',child: const Icon(Icons.add),), // This trailing comma makes auto-formatting nicer for build methods.); }
1. 必须是 子组件:平行的都不行:
2. 子组件获取 InheritedWidget 中的数据 通过:
InheritedDatum.of(context)?.count
3. 子组件不能仅 通过调用 InheritedWidget 中的方便实现 子组件刷新
小结:
InheritedWidget 的适用场景:子组件共享 父组件中的数据;但不具备 修改更新 父组件中数据的 能力!下面介绍的 ChangeNotifier 则具备 上下 更新数据的能力
provider是基于InheritedWidget 的包装 ;为了在Provider中进行数据共享首先我们需要为其定义一个数据模型,为了能够订阅数据的状态通常会让这个数据模型来继承
ChangeNotifier,达到更新的目的; 使用前先导入:
provider: ^6.0.5dependencies:flutter:sdk: flutterprovider: ^6.0.5
之前的总结: https://johns.blog.csdn.net/article/details/122139508
需要在父节点中使用以下 组件来完成 子组件的更新:按照自己 更新逻辑的 复杂度。按照实际需要选取适合的 模型
- ChangeNotifierProvider
- ProxyProvider
- MultiProvider
- Consumer
效果如下:
父组件 和 子组件都可以 实现对数据的更新
脚本结构:
counter.dart
import 'package:flutter/cupertino.dart';class Counter with ChangeNotifier {int _count = 0;int get count => _count;void increment() {_count++;notifyListeners();}void set(int count) {_count = count;notifyListeners();} }
widget_child0.dart
import 'package:untitled1/counter.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart';class WidgetChild0 extends StatelessWidget {const WidgetChild0({Key? key}) : super(key: key);Widget build(BuildContext context) {return Container(color: Colors.blue,height: 40,width: 80,child: GestureDetector(behavior: HitTestBehavior.opaque,onTap: () {context.read
().set(0);print('WidgetChild0');},child: Center(child: Text('${context.watch ().count}',style: TextStyle(color: Colors.white),),),),);} } widget_child1.dart
import 'package:untitled1/counter.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart';class WidgetChild1 extends StatelessWidget {const WidgetChild1({Key? key}) : super(key: key);Widget build(BuildContext context) {return Container(color: Colors.blue,height: 40,width: 80,child: GestureDetector(behavior: HitTestBehavior.opaque,onTap: () {context.read
().set(1);print('WidgetChild1');},child: Center(child: Text('${context.watch ().count}',style: TextStyle(color: Colors.white),),),),);} } main.dart
class MyApp extends StatelessWidget {const MyApp({super.key});// This widget is the root of your application.@overrideWidget build(BuildContext context) {return MaterialApp(title: 'Flutter Demo',theme: ThemeData(primarySwatch: Colors.blue,),home: ChangeNotifierProvider(create: (_) => Counter(),child: const MyHomePage(title: 'Flutter Demo Home Page'),),//home: const MyHomePage(title: 'Flutter Demo Home Page'),);} }
Widget build(BuildContext context) {return Scaffold(appBar: AppBar(// Here we take the value from the MyHomePage object that was created by// the App.build method, and use it to set our appbar title.title: Text(widget.title),),body: Center(child: Row(mainAxisAlignment: MainAxisAlignment.spaceAround,// children: const [],children: const [WidgetChild0(), WidgetChild1()],),),floatingActionButton: FloatingActionButton(onPressed: () {context.read
().increment();},tooltip: 'Increment',child: const Icon(Icons.add),), // This trailing comma makes auto-formatting nicer for build methods.);}
也是共享的数据需要放在 父节点中; 再共有的父节点中 都可以对 数据进行修改更新; 实现双向动态数据: 调用
notifyListeners
其中 MultiProvider,Consumer 适合多组 ChangeNotifier ;以实现解耦操作;基本用法和ChangeNotifierProvider 相同;详细可参考:https://johns.blog.csdn.net/article/details/122139508
https://johns.blog.csdn.net/article/details/122139508