Flutter 全局通知 局部刷新 单例
最近总结了一下 Flutter的局部刷新,主要是
1、 InheritedWidget
2、 ValueNotifier
3、 StreamBuilder
4、 StatefulBuilder
5、 Globalkey
1、
class MyInheritedWidget extends InheritedWidget {
final int count;
MyInheritedWidget(Widget child, this.count) : super(child: child);
//封装快速查阅方法
static MyInheritedWidget of(BuildContext context) {
return context.dependOnInheritedWidgetOfExactType<MyInheritedWidget>();
}
@override
bool updateShouldNotify(MyInheritedWidget oldWidget) {
return oldWidget.count!=this.count;
}
}
//在child中调用 则只会刷新child
MyInheritedWidget.of(context).count
2 ValueNotifier类似于KVO 通过监听观察者的变化,进行局部的刷新,一对一的传值刷新方式,比较方便
ValueNotifier<String> _name = ValueNotifier<String>('');
ValueListenableBuilder(
builder: (context, value, child) {
return Text(value);
},
valueListenable: _name,
child: Text('你变化了吗'),
);
ValueNotifier<String> _name = ValueNotifier<String>('');
_name.value = '我变化了’;
3 StreamBuilder类似于通知 通过注册于发送,进行局部刷新,一对多的传值刷新方式,注意销毁
StreamController<String> _streamController;
_streamController = StreamController<String>();
//注册
StreamBuilder(
stream: _streamController.stream,
builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
if (snapshot.hasData) {
return Text(snapshot.data);
}
return Text('未收到数据');
},
)
@override
dispose() {
super.dispose();
_streamController.close();
}
//发送
_streamController.add('我变化了');
4 StatefulBuilder类似于传值 通过局部setState的传递,进行局部刷新,空间内局部刷新,使用范围有限,更多用于 AlertDialog、Bottomsheet
StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
return Column(
mainAxisSize: MainAxisSize.min,
children: List<Widget>.generate(4, (int index) {
return Radio<int>(
value: index,
groupValue: selectedRadio,
onChanged: (int value) {
setState(() => selectedRadio = value);
},
);
}),
);
})
以上的单独使用,只能在类内部进行刷新,但可以通过配合Provider进行全局的传值刷新
5 Globalkey 是全树查找,虽然使用方便,但复杂项目最好不使用;
封装
abstract class GlobalKeyRefreshableWidget extends StatefulWidget {
GlobalKeyRefreshableWidget({Key key})
: super(key: key is GlobalKey ? key : GlobalKey());
void reload() {
if (key is! GlobalKey) {
return;
}
final aKey = key as GlobalKey;
// ignore: invalid_use_of_protected_member
aKey.currentState.setState(() {});
}
}
class RefreshableStatefulWidget extends GlobalKeyRefreshableWidget {
final Widget Function(BuildContext cntext) builder;
RefreshableStatefulWidget({Key key, @required this.builder})
: assert(builder != null),
super(key: key);
@override
State<StatefulWidget> createState() {
return _RefreshableViewState(builder);
}
}
class _RefreshableViewState extends State<RefreshableStatefulWidget> {
final Widget Function(BuildContext cntext) builder;
_RefreshableViewState(this.builder);
@override
Widget build(BuildContext context) {
return builder(context);
}
}
使用
_aRefreshableView = RefreshableStatefulWidget(builder: (BuildContext context) {
return Container(
...
);
}
_aRefreshableView.reload();
通过单例模式 模仿通知进行全局通知,使用方便可扩展也好理解:
class NotificationCenter {
// 工厂模式
factory NotificationCenter() => _getInstance();
static NotificationCenter get instance => _getInstance();
static NotificationCenter _instance;
NotificationCenter._internal() {
// 初始化
}
//单例
static NotificationCenter _getInstance() {
if (_instance == null) {
_instance = new NotificationCenter._internal();
}
return _instance;
}
//创建Map来记录名称
Map<String, dynamic> postNameMap = Map<String, dynamic>();
Map<String, GetObject> getObject = Map<String, GetObject>();
//添加监听者方法
addObserver(String postName, object(dynamic object)) {
postNameMap[postName] = null;
getObject[postName] = object;
}
//发送通知传值
postNotification(String postName, dynamic object) {
//检索Map是否含有postName
if (postNameMap.containsKey(postName)) {
postNameMap[postName] = object;
getObject[postName](object);
}
}
//移除通知
removeNotification(String postName) {
if (postNameMap.containsKey(postName)) {
postNameMap.remove(postName);
}
}
}
使用:
NotificationCenter.instance.postNotification('HomeRefreash', 'refreash');
注册:
NotificationCenter.instance.addObserver('HomeRefreash', (object){
}
记得销毁
NotificationCenter.instance.removeNotification('HomeRefreash');
刚着手进行总结,肯定会有这样那样的漏洞,也肯定会有更安全方便的方法,希望大佬指正。