写点什么

【Flutter 专题】88 初识状态管理 Bloc (三)

发布于: 1 小时前
【Flutter 专题】88 初识状态管理 Bloc (三)

      小菜刚学习了 FlutterBloc 的基本用法,使用的场景还很简单,主要是单一 Bloc 的应用,今天小菜继续尝试多个 Bloc 共用的场景;

      小菜继续完善前两节的 Demo,添加了随机变更背景色的功能(并没有实际意义,仅为了学习新知识点而已);

FlutterBloc

MultiBlocProvider

      对于多个 Bloc 的应用场景,小菜尝试了如下三种方式:

方案一:

      在 build() 外创建和初始化 Bloc;小菜认为这种方式一定程度上扩大了 Bloc 的作用域;


NumberBloc _numBloc = NumberBloc();ColorBloc _colorBloc = ColorBloc();  @overrideWidget build(BuildContext context) {  return BlocBuilder<NumberBloc, int>(      bloc: _numBloc,      condition: (previousState, state) {        print('BlocPage.condition->$previousState==$state');        return state <= 30 ? true : false;      },      builder: (context, count) {        return BlocBuilder<ColorBloc, Color>(            bloc: _colorBloc,            builder: (context, color) {              return Scaffold(                  appBar: AppBar(title: Text('Bloc Page'), actions: <Widget>[_settingWid()]),                  body: Container(color: _colorBloc.state, child: _numberWid()),                  floatingActionButton: _floatingWid());            });      });}
复制代码
方案二:

      通过多个 BlocProvider 嵌套方式对 Bloc 进行创建;小菜认为这种方式嵌套层级较多,略微有一些繁琐;


@overrideWidget build(BuildContext context) {  return BlocProvider(      create: (BuildContext context) => _numBloc = NumberBloc(),      child: BlocBuilder<NumberBloc, int>(          bloc: _numBloc,          condition: (previousState, state) {            print('BlocPage.condition->$previousState==$state');            return state <= 30 ? true : false;          },          builder: (context, count) {            return BlocProvider(                create: (BuildContext context) => _colorBloc = ColorBloc(),                child: BlocBuilder<ColorBloc, Color>(                    bloc: _colorBloc,                    builder: (context, color) {                      return Scaffold(                          appBar: AppBar(title: Text('Bloc Page'), actions: <Widget>[_settingWid()]),                          body: Container(color: _colorBloc.state, child: _numberWid()),                          floatingActionButton: _floatingWid());                    }));          }));}
复制代码
方案三:

      便是采用 MultiBlocProvider 聚合绑定方式,作为一个 WidgetBlocProvider 方式聚合创建和初始化,小菜更倾向于这种方式,层级更清晰简洁;


@overrideWidget build(BuildContext context) {  return MultiBlocProvider(      providers: [        BlocProvider(create: (BuildContext context) => _numBloc = NumberBloc()),        BlocProvider(create: (BuildContext context) => _colorBloc = ColorBloc())      ],      child: BlocBuilder<NumberBloc, int>(          bloc: _numBloc,          condition: (previousState, state) {            print('BlocPage.condition->$previousState==$state');            return state <= 30 ? true : false;          },          builder: (context, count) {            return BlocBuilder<ColorBloc, Color>(                bloc: _colorBloc,                builder: (context, color) {                  return Scaffold(                      appBar: AppBar(title: Text('Bloc Page'), actions: <Widget>[_settingWid()]),                      body: Container(color: _colorBloc.state, child: _numberWid()),                      floatingActionButton: _floatingWid());                });          }));}
复制代码


MultiBlocListener

      对于多个 Bloc 的场景,对于其 Bloc 的监听也可以有多种方式;

方案一:

      对应于 BlocProvider 的方式,小菜合并前两种,尝试 listener 嵌套方式进行监听;


@overrideWidget build(BuildContext context) {  return BlocProvider(      create: (BuildContext context) => _numBloc = NumberBloc(),      child: BlocListener<NumberBloc, int>(          bloc: _numBloc,          listener: (context, state) => print('BlocListener--->NumberBloc--->$state'),          child: BlocBuilder<NumberBloc, int>(              bloc: _numBloc,              condition: (previousState, state) {                print('BlocPage.condition->$previousState==$state');                return state <= 30 ? true : false;              },              builder: (context, count) {                return BlocProvider(                    create: (BuildContext context) => _colorBloc = ColorBloc(),                    child: BlocListener<ColorBloc, Color>(                        bloc: _colorBloc,                        listener: (context, state) => print('BlocListener--->ColorBloc--->$state'),                        child: BlocBuilder<ColorBloc, Color>(                            bloc: _colorBloc,                            builder: (context, color) {                              return ScaffoldappBar: AppBar(title: Text('Bloc Page'), actions: <Widget>[_settingWid()]),                                  body: Container(color: _colorBloc.state, child: _numberWid()),                                  floatingActionButton: _floatingWid());                            })));              })));}
复制代码
方案二:

      MultiBlocListener 作为一个 Widget,将 listener 聚合在一起;效果完全相同,但消除了嵌套提高了 Code 可读性;


@overrideWidget build(BuildContext context) {  return MultiBlocProvider(      providers: [        BlocProvidercreate: (BuildContext context) => _numBloc = NumberBloc()),        BlocProvider(create: (BuildContext context) => _colorBloc = ColorBloc())      ],      child: MultiBlocListener(          listeners: [            BlocListener<NumberBloc, int>(listener: (context, state) => print('BlocListener--->NumberBloc--->$state')),            BlocListener<ColorBloc, Color>(listener: (context, state) => print('BlocListener--->ColorBloc--->$state'))          ],          child: BlocBuilder<NumberBloc, int>(              bloc: _numBloc,              condition: (previousState, state) {                print('BlocPage.condition->$previousState==$state');                return state <= 30 ? true : false;              },              builder: (context, count) {                return BlocBuilder<ColorBloc, Color>(                    bloc: _colorBloc,                    builder: (context, color) {                      return Scaffold(                          appBar: AppBar(title: Text('Bloc Page'), actions: <Widget>[_settingWid()]),                          body: Container(color: _colorBloc.state, child: _numberWid()),                          floatingActionButton: _floatingWid());                    });              })));}
复制代码


小感想

      小菜尝试了 ProviderBloc 两种状态管理工具,均是对 Stream 的操作,小菜认为各有各的优势,不能互相替代;      Bloc 方式最大的优势是把页面 UI 与业务逻辑拆分的更清晰,不管是 MVC 或 MVP 方式都更方便的融入应用;Provider 的应用更加简单,无需考虑拆分的情况;      小菜在了解源码的时候发现一个有趣的现象,FlutterBloc 也是对 Provider 的一种封装;



      现在针对状态管理的方式还有很多其他方式,小菜认为无需强制使用某一种,选择适合自己对就好;



      FlutterBloc 案例源码


      小菜对 Bloc 的尝试暂时告一个段落,对于更高级的用法在实际应用中再进行尝试和学习;如有错误,请多多指导!


来源: 阿策小和尚

发布于: 1 小时前阅读数: 3
用户头像

还未添加个人签名 2021.05.13 加入

Android / Flutter 小菜鸟~

评论

发布
暂无评论
【Flutter 专题】88 初识状态管理 Bloc (三)