Flutter 全局通知 局部刷新 单例

804 阅读2分钟

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');

刚着手进行总结,肯定会有这样那样的漏洞,也肯定会有更安全方便的方法,希望大佬指正。