BLoC
BLoC表示为业务逻辑组件 (Business Logic Component),由谷歌在2018的 DartConf 首次提出------其诞生可以说是为了解耦。
在了解该框架之前需要了解;

  1. Stream
    这个名词跟其他语言里某个XX有个共同的名字------管道。
    运作时,考虑为一个带有两端的管道(Stream),当你将某物插入(通常StreamController控制插入)管道时(入口为sink),它会在管道内流动并从另一端流出(出口为stream)。
//建一个类ApplicationBloc   --------   记住这个类名字BehaviorSubject<int> _appEvent = BehaviorSubject<int>();   //该BehaviorSubject也是广播 StreamController,它返回一个Observable,而不是Stream。Sink<int> get _appEventSink => _appEvent.sink;    //Widgets 通过 Sinks 向 BLoC 发送事件(event)Stream<int> get appEventStream => _appEvent.stream;   //BLoC 通过流(stream)通知小部件(widgets)

(BehaviorSubject,不知道啥的向下看)

  • Stream中的关键词
    从值,事件,对象,集合,映射,错误甚至另一个流,又或者换句话说,可以由stream传递任何类型的数据。那么,怎么知道传递的类别呢?
StreamController control= StreamController();//监听StreamController 的stream属性,就可以时刻关注到传递的内容StreamSubscription subscription = control.stream.listen((data) => print('$data'));control.sink.add(6666);control.close();

上述是Stream单订阅的一种表现方式。那么再看看另外一种形态 ----- 广播流。

StreamController<int> ctrl = StreamController<int>.broadcast();StreamSubscription subscription = ctrl.stream.where((value) => (value % 2 == 0)).listen((value) => print('$value'));for(int i=1; i<11; i++){ctrl.sink.add(i);}//一般在dispose方法中close掉ctrl.close();

另外一个关键词,StreamTransformer ---- 控制Stream内部数据的处理。
StreamTransformer可以用进行任何类型的处理,例如:
过滤(filtering):根据任何类型的条件过滤数据,
重新组合(regrouping):重新组合数据,
修改(modification):对数据应用任何类型的修改,
将数据注入其他流,
缓冲,
处理(processing):根据数据进行任何类型的操作/操作,

即把流转换为流。

  1. RxDart
    简单来说,RxDart 扩展了原始的Dart Streams API并提供了StreamController的 3个主要变体:PublishSubjectBehaviorSubjectReplaySubject涵盖着事件订阅的概念,三者返回的都是Observable

  2. 反应式编程
    反应式编程是使用异步数据流进行编程,换句话说一个事件由数据流触发时,其连带的所有内容都会被传送,即让整个行为变得异步。

看到这里,结合1中ApplicationBloc那里注册的BehaviorSubject广播,我们可以在需要发送广播的地方:

//在ApplicationBloc 中添加该方法
void sendAppEvent(int type) {_appEventSink.add(type);}
//在build中初始化
final ApplicationBloc bloc = BlocProvider.of<ApplicationBloc>(context);
//需要调用的地方进行调用
bloc.sendAppEvent(Constant.TYPE_SYS_UPDATE);
//在接收的地方
BlocProvider<ApplicationBloc>(bloc: ApplicationBloc(),child: BlocProvider(child: XX(), bloc: null),)

其中的BlocProvider,现在通用写法是

import 'dart:async';import 'package:flutter/material.dart';abstract class BlocBase {Future getData({String labelId, int page});Future onRefresh({String labelId});Future onLoadMore({String labelId});void dispose();
}Type _typeOf<T>() => T;class BlocProvider<T extends BlocBase> extends StatefulWidget {BlocProvider({Key key,@required this.child,@required this.bloc,}): super(key: key);final Widget child;final T bloc;@override_BlocProviderState<T> createState() => _BlocProviderState<T>();static T of<T extends BlocBase>(BuildContext context){final type = _typeOf<_BlocProviderInherited<T>>();_BlocProviderInherited<T> provider =context.ancestorInheritedElementForWidgetOfExactType(type)?.widget;return provider?.bloc;}
}class _BlocProviderState<T extends BlocBase> extends State<BlocProvider<T>>{@overridevoid dispose(){widget.bloc?.dispose();super.dispose();}@overrideWidget build(BuildContext context){return new _BlocProviderInherited<T>(bloc: widget.bloc,child: widget.child,);}
}
//由于使用了InheritedWidget,它现在可以调用context.ancestorInheritedElementForWidgetOfExactType()函数,它是一个O(1),这意味着祖先的检索是立即的
class _BlocProviderInherited<T> extends InheritedWidget {_BlocProviderInherited({Key key,@required Widget child,@required this.bloc,}) : super(key: key, child: child);final T bloc;@overridebool updateShouldNotify(_BlocProviderInherited oldWidget) => false;
}

在这里只是简单了解下,有需要更清晰讲解的可以去看这是一个链接

除了自己学习怎么运用BLoc之外,还可以去https://pub.dartlang.org/packages/去搜索BLoc添加某人上传的依赖(还需要添加flutter_bloc辅助运用)。后者简单了许多。举个简单的例子

import 'dart:async';
import 'package:bloc/bloc.dart';
import 'package:flutter_acesmart/entity/banner_entity.dart';
import 'package:flutter_acesmart/entity/base_entity.dart';
import 'package:flutter_acesmart/http/index.dart';import 'package:flutter_acesmart/http/robort_index.dart';import 'home_event.dart';//HomeEvent和HomeState是我定义在home_event的类,HomeEvent为事件触发,HomeState为事件处理后或之前的状态。class HomeBloc extends Bloc<HomeEvent, HomeState> {@overrideHomeState get initialState => HomeBannerLoading();//这个是必须实现的方法@overrideStream<HomeState> mapEventToState(HomeEvent event) async* {if (event is HomeBannerLoad) {yield* mapLoadBannerToState();}}Stream<HomeState> mapLoadBannerToState() async* {try {List<BannerEntity> bannerEntitys = await _getBanners();yield HomeBannerLoaded(bannerEntitys);//fixme:获取机器人保留的数据或者initstate中disparch} catch (e) {yield LoadError(e);//在HomeState中定义的错误状态方法}}//不用加try-catch,调用层已捕获了//BannerEntity是定义的mode类Future<List<BannerEntity>> _getBanners() async {Response response = await HomeApi.getBanners();BaseEntity<List> baseEntity = BaseEntity.fromJson(response.data);List<BannerEntity> bannerEntitys = baseEntity.data.map((e) {return BannerEntity.fromJson(e);}).toList();return bannerEntitys;}}

下main看看HomeEvent和HomeState(其实可以把他们放在一个类里面,我是觉得放在一起也挺好)

import 'package:equatable/equatable.dart';
import 'package:flutter_acesmart/entity/banner_entity.dart';
import 'package:meta/meta.dart';abstract class HomeEvent extends Equatable {HomeEvent([List props = const []]) : super(props);
}abstract class HomeState extends Equatable {HomeState([List props = const []]) : super(props);
}
///加载主页数据
//   event
class HomeBannerLoad extends HomeEvent {@overrideString toString() {return 'HomeBannerLoad';}
}
//event需要传递参数时
class lampChange extends HomeEvent{final int light;lampChange({@required this.light}): assert(light != null),super([light]);@overrideString toString() {return 'lampChange';}
}///Stateclass HomeBannerLoading extends HomeState {@overrideString toString() {return 'HomeBannerLoading';}
}
//banner下载完毕状态切换,同时把数据绑定传送
class HomeBannerLoaded extends HomeState {List<BannerEntity> banners;HomeBannerLoaded(this.banners) : super([banners]);@overrideString toString() {return 'ProjectBannerLoaded{banners: ${banners?.length}}';}
}class LoadError extends HomeState {Exception exception;LoadError(this.exception) : super([exception]);@overrideString toString() {return 'HomeLoadError';}
}

在需要调用的地方

class HomePage extends StatefulWidget{@overrideState<StatefulWidget> createState() {return new HomePageState();}}class HomePageState extends State<HomePage>with TickerProviderStateMixin {HomeBloc homeBloc ;List<BannerEntity> banners;@overridevoid initState() {super.initState();homeBloc = HomeBloc();banners ??= [];//调用banner下载eventhomeBloc.dispatch(HomeBannerLoad());}@overrideWidget build(BuildContext context) {LogUtil.e("HomePage build......");return Center(child: BlocListener<HomeBloc, HomeState>(bloc: homeBloc,listener: (context, state) {if (state is HomeBannerLoaded) {banners = state.banners; //绑定数据} else if(state is LoadError) {DisplayUtil.showMsg(context, exception: state.exception);}},child: BlocBuilder<HomeBloc, HomeState>(bloc: homeBloc,builder: (context, state) {return Stack(children: <Widget>[Scaffold(.......body: Builder(builder: (context) {return Stack()],),......

大致的使用流程就是这样啦。

flutter 解耦框架BLoC在网络请求中的应用相关推荐

  1. dio java,Flutter基础(十一)网络请求(Dio)与JSON数据解析

    本文首发于微信公众号「后厂技术官」 前言 在Android开发中如果我们想要请求网络,可以使用HttpClent.HttpURLConnection,但在项目中一般都会使用OkHttp和Retrofi ...

  2. 网络请求中常见的加密机制和加密算法理解 流量加密

    请求安全性: 服务器端在接收到请求的时候,要主动鉴别该请求是否有效,是否可接受. token:已登陆用户的识别码 解决的问题:用户调用接口时,不用每次都带上用户名和密码,避免了频繁在网络中传输密码被截 ...

  3. Android 利用an框架快速实现网络请求(含下载上传文件)

    作者:Bgwan 链接:https://zhuanlan.zhihu.com/p/22573081 来源:知乎 著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. an框架的网络框架 ...

  4. uni-app——一种通过Nginx反向代理处理302重定向请求解决网络请求中无法获取Cookie的解决方案

    问题描述 小程序中不会自动保存和发送Cookie 使用插件(https://uniapp.dcloud.io/api/request/request)方法不能解决302重定向情况下获取Cookie 小 ...

  5. 网络请求中常见的加密机制和加密算法理解

    请求安全性: 服务器端在接收到请求的时候,要主动鉴别该请求是否有效,是否可接受. token:已登陆用户的识别码 解决的问题:用户调用接口时,不用每次都带上用户名和密码,避免了频繁在网络中传输密码被截 ...

  6. Android网络请求中的回调

    需求:高效地向服务器请求数据并解析. 涉及的主要工具类: HttpManager 大哥类.最重要的类,封装了GET和POST方法.所有的参数都要经过这个类发送给服务器. HttpRequestList ...

  7. android中网络请求中页面关闭了会怎么样

    这是我在面试的时候,别人问的,其实 ,在实际开发中,并没有怎么遇到: 如果activity中开启了一个网络请求,正在请求中的时候,activity关闭了,那网络请求会怎么样? 因为之前没有遇到过这个问 ...

  8. swift 网络请求中含有特殊字符的解决方案

    在网络请求时,URL出现中文或特殊字符时会造成请求失败,通常可使用  addingPercentEncoding(withAllowedCharacters: CharacterSet) 方法进行解决 ...

  9. 网络请求中的cookie与set-Cookie的交互模式和作用

    首先我们需要思考,很多问题. 1.当很多人访问统一网络服务器,服务器如何来区分不同的用户呢? 答:sessionid,sessionid保证了浏览器和服务器唯一性的通信凭证号码,session保存在服 ...

最新文章

  1. 学自动化必知:20个传感器原理及应用动图
  2. Python第一次写的代码
  3. 加载特征主数据自动删除重复关键值
  4. http post,get,put,delete区别(收集整理)
  5. 为什么c相电路在前面_三相电路分析
  6. 龙芯3A4000 VNC配置
  7. c 调用c语言dll数组,C#调用C类型dll入参为struct的问题详解
  8. 字符串处理,查询第一个不是 0 的字符的位置
  9. fidde调试手机_实操:手机上用Fiddler调试页面(嘎)
  10. 【图像处理】人脸检测--皱纹---变老特效
  11. 性能测试工具JMeter的安装及环境配置--Windows和Linux
  12. 阿里云iconfont使用方法
  13. 商业广告的本质在于其商业性 在于激发对品牌的想象
  14. Unity游戏神经网络版坦克大战
  15. (九)C#之WinForm程序设计-升级版文本编辑器
  16. 美妆护肤做短视频,利用选题策划来涨粉?
  17. Git学习总结(3)
  18. POJ_1849 Two
  19. MATLAB中的多项式的四则运算与求根方法
  20. Qgis 使用QuickOSM插件导入开源地图

热门文章

  1. Linux 批量修改文件名(前缀或后缀)
  2. DenseFuse :A Fusion Approach to Infrared and Visible Images解读
  3. C语言-编写程序,找出2~100以内的所有质数(素数)。
  4. python http2_实战 | Python使用HTTP2实现苹果原生推送
  5. MCMC(二):MCMC采样和M-H采样
  6. 苹果plus HTML高度,苹果6S/6S Plus怎么查看海拔高度?
  7. Hadoop3 - HDFS 文件存储策略
  8. STM32 PS2游戏摇杆 测试
  9. 【Hive】窗口函数详解
  10. PyCharm远程开发调试