Bloc模式的出现, 主要用于分离UI组件和逻辑业务, 特别对于复杂的app状态管理, 能有效做到UI和业务解耦.
简单方法 Simple Bloc Provider
BlocProvider直接继承InheritedWidget, 这样其子Widget都能访问内部数据. 但是因为没有dispose方法,因此无法释放资源.
对于简单应用, 完全可以使用该方法而不必关心是否会浪费资源拖慢系统.
import 'package:flutter/material.dart';
import 'bloc_base.dart';
class BlocProvider<T extends BlocBase> extends InheritedWidget {
final T bloc;
final Widget child;
BlocProvider({
Key key,
@required this.bloc,
@required this.child,
});
static T of<T extends BlocBase>(BuildContext context) {
BlocProvider<T> provider =
context.inheritFromWidgetOfExactType(BlocProvider);
return provider.bloc;
}
@override
bool updateShouldNotify(BlocProvider<T> oldWidget) {
return bloc != oldWidget.bloc;
}
}
常规方法 Standard Bloc Provider
BlocProvider继承StatefulWidget, 可以确保在不需要的时候释放Bloc分配的资源.
这很好用但从性能角度来看并不是最佳的。
context.ancestorWidgetOfExactType()是一个为时间复杂度为O(n)的函数,为了检索某种类型的祖先,它将对widget树做向上导航,从上下文开始,一次递增一个父,直到完成。如果从上下文到祖先的距离很小(即O(n)结果很少),则可以接受对此函数的调用,否则应该避免。
https://www.jianshu.com/p/f03707b712a4
import 'package:flutter/material.dart';
import 'bloc_base.dart';
class BlocProvider<T extends BlocBase> extends StatefulWidget {
final T bloc;
final Widget child;
BlocProvider({Key key, @required this.bloc, @required this.child});
static Type _typeOf<T>() => T;
@override
_BlocProviderState<T> createState() => _BlocProviderState<T>();
static T of<T extends BlocBase>(BuildContext context) {
final type = _typeOf<BlocProvider<T>>();
BlocProvider<T> provider = context.ancestorWidgetOfExactType(type);
return provider?.bloc;
}
}
class _BlocProviderState<T extends BlocBase> extends State<BlocProvider<T>> {
@override
void dispose() {
widget.bloc?.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return widget.child;
}
}
复杂方法 Complex Bloc Provider
方法已来于StatefulWidget, 并结合InheritedWidget, 该方法的优点是性能好.
由于使用了InheritedWidget,它现在可以调用context.ancestorInheritedElementForWidgetOfExactType()函数,它是一个O(1),这意味着祖先的检索是立即的.
https://www.jianshu.com/p/f03707b712a4
import 'package:flutter/material.dart';
import 'bloc_base.dart';
class BlocProvider<T extends BlocBase> extends StatefulWidget {
final T bloc;
final Widget child;
BlocProvider({Key key, @required this.bloc, @required this.child})
: super(key: key);
static Type _typeOf<T>() => T;
static T of<T extends BlocBase>(BuildContext context) {
final type = _typeOf<_BlocProviderInherited<T>>();
_BlocProviderInherited<T> provider =
context.ancestorInheritedElementForWidgetOfExactType(type)?.widget;
return provider?.bloc;
}
@override
_BlocProviderState createState() => _BlocProviderState<T>();
}
class _BlocProviderState<T extends BlocBase> extends State<BlocProvider<T>> {
/// 便于资源的释放
@override
void dispose() {
widget.bloc?.dispose();
super.dispose();
}
/// 返回继承了InheritedWidget的实例
@override
Widget build(BuildContext context) {
return _BlocProviderInherited<T>(
bloc: widget.bloc,
child: widget.child,
);
}
}
class _BlocProviderInherited<T> extends InheritedWidget {
final T bloc;
final Widget child;
_BlocProviderInherited({
Key key,
@required this.child,
@required this.bloc,
}) : super(key: key, child: child);
@override
bool updateShouldNotify(_BlocProviderInherited oldWidget) => false;
}
当然, pub上已经有不少的bloc插件, 轮子早有人造好了, 我们真正开发中能借用还是尽量借用. 但了解一些必要的原理还是很有必要的.