美文网首页Flutter
Flutter学习笔记状态管理学习之bLoc

Flutter学习笔记状态管理学习之bLoc

作者: Ugly_K | 来源:发表于2019-02-18 19:50 被阅读3次

    Flutter学习笔记 状态管理学习之bLoc

    1.创建一个状态管理

    首先使用Stream来实现的bLoc状态管理如果不手动回收就会一直占用资源,所以在设计之初就需要强调使用完成之后的回收;

    abstract class BlocBase {
      void dispose();
    }
    

    这里的Demo描述的是一个计数参数的管理:

    class IncrementBloc implements BlocBase {
      int _counter;
    
      StreamController<int> _counterController = StreamController<int>.broadcast();
    
      StreamSink<int> get _inAdd => _counterController.sink;
    
      Stream<int> get outCounter => _counterController.stream;
    
      StreamController _actionControll = StreamController.broadcast();
    
      StreamSink get incrementCounter => _actionControll.sink;
    
      IncrementBloc() {
        _counter = 0;
        _actionControll.stream.listen(_handleLogic);
      }
    
      void _handleLogic(data) {
        _counter += 1;
        _inAdd.add(_counter);
      }
    
      @override
      void dispose() {
        _actionControll.close();
        _counterController.close();
      }
    
    }
    

    解释一下设计的属性:

    • StreamController<int>:Stream管理类,这里主要控制的是计数参数的变化以及监听;
    • _inAdd:计数写入
    • outCounter:计数输出
    • _actionControll:动作Stream管理类,这里主要是用于监听它的变化来完成对计数管理的动作;
    • incrementCounter:动作写入;

    工作流程很清晰,也就是当对incrementCounter写入的时候,其监听事件_handleLogic(data)触发,计数增加1,然后dispose()方法则将两个Stream管理类进行关闭;

    2.如何去使用

    使用StreamBuilder<T>包裹需要动态显示的控件进行使用:

    StreamBuilder<int>(
      stream: bloc.outCounter,
      initialData: bloc._counter,
      builder: (BuildContext context, AsyncSnapshot<int> snapshot) {
        return Text('now index is ${snapshot.data}');
      },
    )
    

    当然需要实例化一个状态管理类:

    final IncrementBloc bloc = IncrementBloc();
    

    接下来只需要对bloc进行操作就可以了:

    bloc.incrementCounter.add(null);
    

    Demo:

    class CounterPage extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        final IncrementBloc bloc = IncrementBloc();
        return new Scaffold(
          appBar: AppBar(
            title: Text('bLoc test page'),
          ),
          body: Center(
            child: StreamBuilder<int>(
              stream: bloc.outCounter,
              initialData: bloc._counter,
              builder: (BuildContext context, AsyncSnapshot<int> snapshot) {
                return Text('now index is ${snapshot.data}');
              },
            ),
          ),
          floatingActionButton: new FloatingActionButton(
            backgroundColor: Colors.blue,
            child: Icon(
              Icons.add,
              color: Colors.white,
            ),
            onPressed: () {
              bloc.incrementCounter.add(null);
            },
          ),
        );
      }
    }
    

    当点击FAB的时候,就会将计数管理+1,然后居中文字动态显示,避免了StatefulWidget中动辄全部刷新的情况;
    但是当我们用这种方法使用StatelessWidget来替代StatefulWidget的时候,并没有类似dispose的方法来让我们执行Stream关闭的操作:

    所以要么就使用StatefulWidget来实现,但是并不使用其setState方法来全部刷新;

    3.使用StatefulWidget封装

    class BlocProvider<T extends BlocBase> extends StatefulWidget {
      final T bloc;
      final Widget child;
    
      BlocProvider({
        Key key,
        @required this.child,
        @required this.bloc,
      }) : super(key: key);
    
      @override
      _BlocProviderState createState() => new _BlocProviderState();
    
      static T of<T extends BlocBase>(BuildContext context) {
        final type = _typeOf<BlocProvider<T>>();
        BlocProvider<T> provider = context.ancestorWidgetOfExactType(type);
        return provider.bloc;
      }
    
      static Type _typeOf<T>() => T;
    }
    
    class _BlocProviderState extends State<BlocProvider<BlocBase>> {
      @override
      Widget build(BuildContext context) {
        return widget.child;
      }
    
      @override
      void dispose() {
        // TODO: implement dispose
        widget.bloc.dispose();
        super.dispose();
      }
    }
    

    使用:

    IncrementBloc bloc = new IncrementBloc();
    Navigator.push(
      context,
      MaterialPageRoute(builder: (context) {
        return BlocProvider<IncrementBloc>(
            child: CounterPage(),
            bloc: bloc);
      }),
    );
    

    这样的话,BlocProvider在退出销毁dispose的时候,就会自动调用状态管理中实现的销毁dispose方法了,当然这明显是一个局部状态管理;

    全局状态管理的话,在runApp()处实现一个就行了。

    相关文章

      网友评论

        本文标题:Flutter学习笔记状态管理学习之bLoc

        本文链接:https://www.haomeiwen.com/subject/yypzeqtx.html