Flutter學習筆記狀態(tài)管理學習之bLoc

Flutter學習筆記 狀態(tài)管理學習之bLoc

1.創(chuàng)建一個狀態(tài)管理

首先使用Stream來實現(xiàn)的bLoc狀態(tài)管理如果不手動回收就會一直占用資源,所以在設計之初就需要強調使用完成之后的回收;

abstract class BlocBase {
  void dispose();
}

這里的Demo描述的是一個計數(shù)參數(shù)的管理:

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管理類,這里主要控制的是計數(shù)參數(shù)的變化以及監(jiān)聽;
  • _inAdd:計數(shù)寫入
  • outCounter:計數(shù)輸出
  • _actionControll:動作Stream管理類,這里主要是用于監(jiān)聽它的變化來完成對計數(shù)管理的動作;
  • incrementCounter:動作寫入;

工作流程很清晰,也就是當對incrementCounter寫入的時候,其監(jiān)聽事件_handleLogic(data)觸發(fā),計數(shù)增加1,然后dispose()方法則將兩個Stream管理類進行關閉;

2.如何去使用

使用StreamBuilder<T>包裹需要動態(tài)顯示的控件進行使用:

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

當然需要實例化一個狀態(tài)管理類:

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的時候,就會將計數(shù)管理+1,然后居中文字動態(tài)顯示,避免了StatefulWidget中動輒全部刷新的情況;
但是當我們用這種方法使用StatelessWidget來替代StatefulWidget的時候,并沒有類似dispose的方法來讓我們執(zhí)行Stream關閉的操作:

所以要么就使用StatefulWidget來實現(xiàn),但是并不使用其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的時候,就會自動調用狀態(tài)管理中實現(xiàn)的銷毀dispose方法了,當然這明顯是一個局部狀態(tài)管理;

全局狀態(tài)管理的話,在runApp()處實現(xiàn)一個就行了。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容