【flutter 起步走】flutter共享数据利器,InheritedWidget原理探秘_flutter inheritedwidget原理(1)

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新HarmonyOS鸿蒙全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img

img
img
htt

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上鸿蒙开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip204888 (备注鸿蒙)
img

正文

InheritedWidget和 React 中的 context 功能类似,和逐级传递数据相比,它们能实现组件跨级传递数据。InheritedWidget的在 widget 树中数据传递方向是从上到下的,这和通知Notification的传递方向正好相反。

二,组件树中的数据共享用法(利用 ValueNotrifier 和 InhertitedWidget 实现简单的状态管理)

  1. 我们首先创建一个MyProvider 继承自InheritedWidget,以存放状态数据,该状态继承自ChangeNotifier,即代码中的model变量。

import ‘package:flutter/widgets.dart’;

///提供状态存储
class MyProvider extends InheritedWidget {
T model;
MyProvider({Key? key,required Widget child,required this.model}) : super(key: key,child:child);

@override
Widget build(BuildContext context) {
return this.child;
}

static MyProvider? of(BuildContext context){
return context.dependOnInheritedWidgetOfExactType<MyProvider>();
}

@override
bool updateShouldNotify(covariant MyProvider oldWidget) {
return false;
}
}

  1. 接下来创建一个Customer,用来实现动态刷新,和局部刷新,原理主要是利用changeNotifier监听器更新数据更新,注册对应监听器刷新Customer的子布局。

///提供状态消费,在状态ValueNotifier更新的时候,自动刷新Customer组件
class Customer extends StatefulWidget{
const Customer({required this.builder,});
final ProviderBuilder builder;

@override
State<Customer> createState() => _CustomerState();
}

class _CustomerState extends State<Customer> {

late MyProvider? provider;

@override
void didChangeDependencies() {
super.didChangeDependencies();
provider=MyProvider.of(context);
if(provider==null) throw “请在祖先节点提供MyProvider”;
provider!.model.addListener(() {
setState(()=>{});
});
}
@override
Widget build(BuildContext context) {
return widget.builder(context,MyProvider.of(context)!.model);
}
}
typedef ProviderBuilder = Widget Function(BuildContext context,T value);

  1. 接着创建一个展示用的widget,包含显示数据的子widget 和 点击刷新数据的 按钮,代码如下:

import ‘package:flutter/material.dart’;
import ‘package:flutter/widgets.dart’;
import ‘package:free/widget/my_provider.dart’;
import ‘package:provider/provider.dart’;

class TestWidget extends StatefulWidget {
const TestWidget({Key? key}) : super(key: key);

@override
State createState() => _TestWidgetState();
}
class TestModel extends ChangeNotifier{
var num=0;

TestModel() : super();
}
class _TestWidgetState extends State {
var model=TestModel();
@override
Widget build(BuildContext context) {
return Scaffold(
body: MyProvider(
model:model,
child: Builder(
builder: (context) {
return Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
MyTextWidget(),
MaterialButton(
color: Colors.blueAccent,
elevation: 10,
onPressed: () {
model.num++;
model.notifyListeners();
},
child: Text(“点击加一”)),
],
),
);
}
),
),
);
}
}
class MyTextWidget extends StatelessWidget {
const MyTextWidget ({Key? key}) : super(key: key);

@override
Widget build(BuildContext context) {
return Customer(builder:(c,value) => Text(“${value.num}”));
}
}

至此,利用InheritedWidgetChangeNotifier实现的简易状态管理库就实现了。该库实现了跨组件共享数据,跨组件更新数据状态,并更新对应的兄弟组件。 这也是一些第三方开源状态库的基本原理。 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-801uLTkK-1656770740524)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/affe1c05fcbe418fbfbb6a166157e10b~tplv-k3u1fbpfcp-zoom-in-crop-mark:1956:0:0:0.image)]

三,InheritedWidget如何共享数据

先看看我们获取 InheritedWidget实例的dependOnInheritedWidgetOfExactType方法,注释翻译如下:

获取给定类型T的最近小部件,它必须是具体InheritedWidget子类的类型,并将此构建上下文注册到该小部件,以便当该小部件更改时(或引入该类型的新小部件,或小部件消失离开),这个构建上下文被重建,以便它可以从那个小部件获取新值。 这通常从of()静态方法中隐式调用,例如Theme.of 。 不应从小部件构造函数或State.initState方法调用此方法,因为如果继承的值发生更改,这些方法将不会再次被调用。为了确保小部件在继承值更改时正确更新自身,只能从构建方法、布局和绘制回调或从State.didChangeDependencies调用(直接或间接)。 不应从State.dispose调用此方法,因为此时元素树不再稳定。要从该方法引用祖先,请将对祖先的引用保存在State.didChangeDependencies中。从State.deactivate中使用此方法是安全的,每当从树中删除小部件时都会调用该方法。 也可以从交互事件处理程序(例如手势回调)或计时器调用此方法,以获取一次值,如果该值不会被缓存并稍后重用。 调用此方法是 O(1),具有较小的常数因子,但会导致更频繁地重建小部件。 一旦小部件通过调用此方法注册对特定类型的依赖关系,它将被重建,并且State.didChangeDependencies将被调用,每当与该小部件相关的更改发生时,直到下一次移动小部件或其祖先之一(例如例如,因为添加或删除了祖先)。 aspect参数仅在T是支持部分更新的InheritedWidget子类时使用,例如InheritedModel 。它指定此上下文所依赖的继承小部件的“方面。 T? dependOnInheritedWidgetOfExactType({ Object? aspect });

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注鸿蒙)
img

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

料的朋友,可以添加V获取:vip204888 (备注鸿蒙)**
[外链图片转存中…(img-u1cih2Eg-1713341840660)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 27
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值