提笔缘由
状况办理伴随着Flutter的开展日益丰厚,如果说响应式是Flutter的特色,那么状况办理的便是完结办法,从开始的provide再到官方认可的provider,还有scoped_model,event_bus,get,riverpod,BloC,redux等等太多。作为开发者,对这些状况办理完结办法能够了解一二,当然由于学疏才浅,我只能略懂。Stream和InheritedWidget两种不同办法完结状况办理,项目中常用的Provider中心便是InheritedWidget,所以经过探究该类来旁边面了解provider,在实践中很少用到InheritedWidget,但他是个幕后英雄。
关联知识点
- InheritedWidget
- ValueNotifier
- ValueListenBuilder
- Builder
- ChangeNotifier
- ValueListenable
类InheritedWidget
结构函数很简略,需求必传一个Widget,由于只有他的child,才能获取到寄存在树梢的数据。
InheritedWidget({Key key,required Widget child})
承继InheritedWidget后有必要override的办法,作用是你来决定通知改变的条件,以便节约资源。
updateShouldNotify(
covariant InheritedWidget oldWidget
) → bool
承继的新类需求一个静态办法 of(context),也是中心的一步,child便是经过of获取在树梢的数据,凭借context.dependOnInheritedWidgetOfExactType办法来获取。
最简略示例
用最简略的比如演示InheritedWidget运用过程,界说类ColorInherited承继InheritedWidget,里边寄存颜色color和巨细size,ColorInherited用于下面的child获取。ColorInherited能够放在Scaffold上下都能够,留意点是需求类Builder促使生成context,否则会由于context问题而报错,第二个留意点是dependOnInheritedWidgetOfExactType办法是泛型,要传入详细类。示例代码如下:
import 'package:flutter/material.dart';
void main() => runApp(MaterialApp(home: ColorInheritedPage()));
class ColorInheritedPage extends StatelessWidget {
const ColorInheritedPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('InheritedWidget演示')),
body: ColorInherited(
size: const Size(300, 100),
color: Colors.brown,
child: Builder(builder: (context) {
var provider = ColorInherited.of(context);
return Container(
height: provider.size.height,
width: provider.size.width,
color: provider.color,
);
}),
),
);
}
}
class ColorInherited extends InheritedWidget {
final Color color;
final Size size;
const ColorInherited({
super.key,
required super.child,
required this.color,
required this.size,
});
static ColorInherited of(BuildContext context) {
var inherited = context.dependOnInheritedWidgetOfExactType<ColorInherited>();
assert(inherited != null, 'error:No ColorInherited ');
return inherited!;
}
@override
bool updateShouldNotify(covariant ColorInherited oldWidget) {
return oldWidget.size != size || oldWidget.color != color;
}
}
计数器示例
在了解InheritedWidget如何运用后,咱们可继续探究。上面比如中是静态数据,页面没有任何改变,现在用他来做个计数器的页面,是一种有改变的状况,需求及时去响应,就能够结合ChangeNotifier类,这个是不是了解的味道,在provider中界说数据类时需求承继他,凭借ChangeNotifier界说自己的数据,寄存一个变量,是需求ValueNotifier类,
//寄存需求监听的变量
class CounterNotify extends ChangeNotifier {
final countState = ValueNotifier<int>(0);
void add() => countState.value++;
}
而ValueListenableBuilder担任在页面上响应改变做到部分改写,ValueNotifier和ValueListenableBuilder配套运用。
有数据源之后,需求凭借InheritedWidget来放在树上,其下child随时取用,这个状况办理类CounterInherited里有个变量是CounterNotify类型的,也便是数据源。
//类似于Provider类
class CounterInherited extends InheritedWidget {
const CounterInherited({
super.key,
required super.child,
required this.counterNotify,
});
final CounterNotify counterNotify;
static CounterInherited of(BuildContext context) {
var inherited = context.dependOnInheritedWidgetOfExactType<CounterInherited>();
assert(inherited != null, '在context中未找到CounterInherited类');
return inherited!;
}
@override
bool updateShouldNotify(covariant CounterInherited oldWidget) {
return oldWidget.counterNotify != counterNotify;
}
}
万事具备,只欠显现在页面上,ValueNotifier和ValueListenableBuilder配套运用,一个担任页面端显现,一个担任状况改变及通知。其实更严格地说是ValueListenable和ValueListenableBuilder配套运用,ValueNotifier只是抽象类ValueListenable的承继者,还有了解的类Animation也是属于ValueListenable,
//结构函数
ValueListenableBuilder({
Key? key,
required ValueListenable<T> valueListenable, //对应数据源的变量
required ValueWidgetBuilder<T> builder,
Widget? child
})
//抽象类ValueListenable的承继者有: ValueNotifier、Animation、RouteInformationProvider、SelectionHandler。
用InheritedWidget和ValueListenable组装的计数器完结,代码如下:
//空安全,Flutter3.3.2
import 'package:flutter/material.dart';
void main() => runApp(MaterialApp(home: CounterInheritedPage()));
class CounterInheritedPage extends StatelessWidget {
const CounterInheritedPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return CounterInherited(
counterNotify: CounterNotify(),
child: Scaffold(
appBar: AppBar(title: const Text('InheritedWidget计数器')),
//需求Builder促使context实例,否则无context
body: Builder(builder: (context) {
var provider = CounterInherited.of(context).counterNotify;
return Center(
child: GestureDetector(
onTap: provider.add,
//部分改写
child: ValueListenableBuilder(
valueListenable: provider.countState,
builder: (context, value, child) {
return Text('${provider.countState.value}');
},
),
),
);
}),
),
);
}
}
//类似于Provider类
class CounterInherited extends InheritedWidget {
const CounterInherited({
super.key,
required super.child,
required this.counterNotify,
});
final CounterNotify counterNotify;
static CounterInherited of(BuildContext context) {
var inherited = context.dependOnInheritedWidgetOfExactType<CounterInherited>();
assert(inherited != null, '在context中未找到CounterInherited类');
return inherited!;
}
@override
bool updateShouldNotify(covariant CounterInherited oldWidget) {
return oldWidget.counterNotify != counterNotify;
}
}
//寄存需求监听的变量
class CounterNotify extends ChangeNotifier {
final countState = ValueNotifier<int>(0);
void add() => countState.value++;
}