Flutter Bloc的使用演示demo

BLoC 全称是Business Logic Component,业务逻辑组件,简称 Bloc。

在这里插入图片描述

1、Stream实现Bloc

1.Bloc 的实现

counter_bloc 类

import 'dart:async';

class CounterBLoC{

  //记录按钮点击的次数
  //被流包裹的数据(可以是任何类型)
  int _counter =0;

  //流控制
  final _counterStreamController =new StreamController<int>();

  //流
  Stream<int> get stream_counter=> _counterStreamController.stream;


   // 通过sink.add发布一个流事件
  void addCount(){
    _counterStreamController.sink.add(++_counter);
  }


   //释放流
   void dispose(){
     _counterStreamController.close();
   }

}

2.BLoC 的使用


import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';


import 'counter_bloc.dart';

class CountPage extends StatefulWidget {
  @override
  _CountPageState createState() => _CountPageState();
}

class _CountPageState extends State<CountPage> {

  //把一些相关的数据请求,实体类变换抽到CounterBLoC这个类里
  //实例化CounterBLoC
  final _bloc = new CounterBLoC();


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("CountBloc"),),
      body: StreamBuilder(
        //监听流,当流中的数据发生变化(调用过sink.add时,此处会接收到数据的变化并且刷新UI)
        stream: _bloc.stream_counter,
        initialData: 0,
        builder: (BuildContext context,AsyncSnapshot<int> snapshot){
          return Center(
            child: Text(snapshot.data.toString(),style: TextStyle(fontSize: 40,fontWeight: FontWeight.w300),),
          );
        },
      ),
      floatingActionButton: _getButton(),
    );
  }

  @override
  void dispose() {
    // TODO: implement dispose
    super.dispose();
    //关闭流
    _bloc.dispose();
  }




  Widget _getButton(){
    return FloatingActionButton(child: Icon(Icons.add),
        onPressed: (){
          // 点击添加;其实也是发布一个流事件
          _bloc.addCount();
        });
  }
}

示例源码
https://github.com/anymyna/flutter-examples/tree/master/flutter_app_bloc_counter

2、RxDart实现Bloc

1.网络请求NetApi 类

import 'dart:convert';

import 'package:http/http.dart' show Client;

import 'beauty_model.dart';

class NetApi {
  Client client = new Client();

  Future<List<BeautyModel>> fetchBeauties() async {
    print("Starting get beauties ..");
    List models = List();
    final response =
        await client.get("http://gank.io/api/data/福利/15/1");
    if (response.statusCode == 200) {
      models = json.decode(response.body)["results"];
      return models.map((model){
        return BeautyModel.fromJson(model);
      }).toList();
    } else {
      throw Exception('Failed to load dog');
    }
  }
}

2.BLoC 类的实现

import 'package:rxdart/rxdart.dart';

import '../bloc_provider.dart';
import 'beauty_model.dart';
import 'net_api.dart';

class BeautyBloc {

  //网络请求的实例
  NetApi _netApi =new NetApi();

  final _beautyFetcher = PublishSubject<List<BeautyModel>>();

  //提供被观察的List<BeautyModel
  Observable<List<BeautyModel>> get beauties =>_beautyFetcher.stream;

  //获取网络数据
  fetchBeauties() async{

    List models = await _netApi.fetchBeauties();

    if(_beautyFetcher.isClosed)return;

    _beautyFetcher.sink.add(models);
  }

  //释放
  dispose(){
    _beautyFetcher?.close();
  }
}

3.BLoC 的使用

import 'package:flutter/material.dart';

import 'beauty_bloc.dart';
import 'beauty_model.dart';

class BeautyPage extends StatefulWidget {
  @override
  _BeautyPageState createState() => _BeautyPageState();
}

class _BeautyPageState extends State<BeautyPage> {
  final _beautyBloc = BeautyBloc();

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    _beautyBloc.fetchBeauties();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("BeautyPage"),
      ),
      body: Container(
          child: StreamBuilder(
              //监听流
              stream: _beautyBloc.beauties,
              builder: (context, AsyncSnapshot<List<BeautyModel>> snapshot) {
                if (snapshot.hasData) {
                  return ListView.builder(
                    itemBuilder: (BuildContext context, int index) {
                      return Card(
                          elevation: 8,
                          shape: RoundedRectangleBorder(
                            borderRadius: BorderRadius.circular(20),
                          ),
                          child: Image.network(
                            snapshot.data[index].url,
                            fit: BoxFit.fill,
                          ));
                    },
                    itemCount: snapshot.data.length,
                  );
                } else if (snapshot.hasError) {
                  return Text('Beauty snapshot error!');
                }
                return Text('Loading Beauties..');
              })),
    );
  }
}

示例源码
https://github.com/anymyna/flutter-examples/tree/master/flutter_app_bloc_rxdart

3、Bloc封装展示

1.BlocProvider

import 'package:flutter/material.dart';

import 'beauty_bloc_example/net_api.dart';

//获类型
Type _typeOf<T>() {
  return T;
}

abstract class BlocBase {
  //一些网络接口API
  NetApi netApi = new NetApi();

  //释放
  void dispose();
}

//更方便的管理Bloc
class BlocProvider<T extends BlocBase> extends StatefulWidget {
  final T bloc; //bloc

  final Widget child; //子Widget

  //构造
  const BlocProvider({Key key,@required this.bloc, @required this.child}) : super(key: key);

  //通过ancestorInheritedElementForWidgetOfExactType获取
  //bloc 实例
  static T of<T extends BlocBase>(BuildContext context) {
    final type = _typeOf<_BlocProviderInherited<T>>();
    _BlocProviderInherited<T> provider =
        context.ancestorInheritedElementForWidgetOfExactType(type)?.widget;
    return provider?.bloc;
  }
  @override
  _BlocProviderState<T> createState() {
    // TODO: implement createState
    return _BlocProviderState();
  }
}

class _BlocProviderState<T extends BlocBase>
    extends State<BlocProvider<BlocBase>> {
  @override

  /// 便于资源的释放
  void dispose() {
    widget.bloc?.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return new _BlocProviderInherited<T>(
      child: widget.child,
      bloc: widget.bloc,
    );
  }
}

class _BlocProviderInherited<T> extends InheritedWidget {
  _BlocProviderInherited({
    Key key,
    @required Widget child,
    @required this.bloc,
  }) : super(key: key, child: child);

  final T bloc;

  @override
  bool updateShouldNotify(_BlocProviderInherited oldWidget) => false;
}

2.BeautyBasePage 类

import 'package:flutter/material.dart';
import 'package:flutter_bloc_example/bloc_provider.dart';

import 'beauty_base_bloc.dart';
import 'beauty_bloc.dart';
import 'beauty_model.dart';

class BeautyBasePage extends StatefulWidget {
  @override
  _BeautyBasePageState createState() => _BeautyBasePageState();
}

class _BeautyBasePageState extends State<BeautyBasePage> {
  @override
  void initState() {
    // TODO: implement initState
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    //拿到 BeautyBaseBloc 实例
    BeautyBaseBloc _bloc= BlocProvider.of<BeautyBaseBloc>(context);
    //获取网络数据
    _bloc.fetchBeauties();

    return Scaffold(
      appBar: AppBar(
        title: Text("BeautyPage"),
      ),
      body: Container(
          child: StreamBuilder(
              stream: _bloc.beauties,
              builder: (context, AsyncSnapshot<List<BeautyModel>> snapshot) {
                if (snapshot.hasData) {
                  print('has data');
                  return ListView.builder(
                    itemBuilder: (BuildContext context, int index) {
                      return Card(
                          elevation: 8,
                          shape: RoundedRectangleBorder(
                            borderRadius: BorderRadius.circular(20),
                          ),
                          child: Image.network(
                            snapshot.data[index].url,
                            fit: BoxFit.fill,
                          ));
                    },
                    itemCount: snapshot.data.length,
                  );
                } else if (snapshot.hasError) {
                  return Text('Beauty snapshot error!');
                }
                return Text('Loading Beauty..');
              })),
    );
  }
}

  1. BlocProvider使用

class BeautyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: "BeautyBloc Demo",
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      //插入 BlocProvider
      home: BlocProvider<BeautyBaseBloc>(
          child: BeautyBasePage(), bloc: new BeautyBaseBloc()),
    );
  }
}

示例源码
https://github.com/anymyna/flutter-examples/tree/master/flutter_app_bloc_collect

4、Bloc开源组件

1.添加依赖:

dependencies:
  bloc: ^0.15.0
  flutter_bloc: ^0.21.0
  1. CounterBloc 依赖bloc
class CounterBloc extends Bloc<CounterEvent, CounterState> {
 @override
 CounterState get initialState => CounterLoading(0);

 @override
 Stream<CounterState> mapEventToState(
   CounterEvent event,
 ) async* {
   if(event is CounterLoad) {
     yield* _mapCounterLoadToState();
   } else if (event is CounterIncrease) {
     yield* _mapCounterIncreaseToState(event);
   } else if (event is CounterDecrease) {
     yield* _mapCounterDecreaseToState(event);
   }
 }

 Stream<CounterState> _mapCounterLoadToState() async* {
   try {
     yield CounterLoaded(0);
   } catch (_) {
     yield CounterUnLoaded(0);
   }
 }

 Stream<CounterState> _mapCounterIncreaseToState(CounterEvent counterEvent) async* {
   if (currentState is CounterLoaded) {
     final int counter = (currentState as CounterLoaded).counter + counterEvent.counter;
     yield CounterLoaded(counter);
     _print(counter);
   }
 }

 Stream<CounterState> _mapCounterDecreaseToState(CounterEvent counterEvent) async* {
   if (currentState is CounterLoaded) {
     final int counter = (currentState as CounterLoaded).counter - counterEvent.counter;
     yield CounterLoaded(counter);
     _print(counter);
   }
 }

 void _print(int counter) {
   print(counter);
 }
}
  1. BlocBuilder 依赖flutter_bloc
class _SecondPageState extends State<SecondPage> {

  @override
  Widget build(BuildContext context) {
    final counterBloc = BlocProvider.of<CounterBloc>(context);
    return Scaffold(
      appBar: AppBar(
        leading: GestureDetector(
          onTap: () => Navigator.pop(context),
          child: Icon(Icons.arrow_back),
        ),
        title: Text('Second Page'),
      ),
      body: BlocBuilder<CounterBloc, CounterState>(
        builder: (context, state) => Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Text(
                'You have pushed the button this many times:',
              ),
              Text(
                '${state.counter}',
                style: Theme.of(context).textTheme.display1,
              ),
            ],
          ),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {counterBloc.dispatch(CounterIncrease(1));},
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

示例源码
https://github.com/anymyna/flutter-examples/tree/master/flutter_app_bloc_demo

致谢
Flutter—BLoC的介绍使用与封装
Flutter响应式编程:Streams和BLoC

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值