Bloc入门之Cubit详解

背景

前面学写了一些基础的Flutter开发知识,但是对于项目的整体架构以及开发模式并没有进行一个系统的学习,经过上网查询,发现目前很多项目采用了Bloc(业务该逻辑组件)这种开发模式,下面就找到了该库的官网

优点

Bloc可以比较轻松地将展示层的代码与业务逻辑分开,从而使您的代码快速,易于测试且可重复使用

动手

首先对于Stream熟悉的同学可以忽略此部分,Java8的新特性里面也有流这部分内容。

从零开始

  1. 从0开始,写个简单的程序认识一下Stream这个类新建一个文件夹:
blocTest
  1. 新建一个test.dart文件,输入以下内容,简单了解以下流这个类型 :
// 返回一个流,流里面是不大于max的数,要注意,每次yield的时候,都会向流里面推数据
Stream<int> countStream(int max) async* {
    for (int i = 0; i < max; i++) {
        yield i;
    }
}
// 使用await等待流中的每个数据,然后返回和,而且是`Future`类型
Future<int> sumStream(Stream<int> stream) async {
    int sum = 0;
    await for (int value in stream) {
        sum += value;
    }
    return sum;
}

void main() async {
  Stream<int> stream = countStream(10);
  int sum = await sumStream(stream);
  print(sum); // 45
}
  1. 预热以后,开始上手,安装库

在根文件夹里面新建一个文件pubspec.yaml并输入以下内容

name: blocTest
environment:
  sdk: ">=2.17.0-0 <3.0.0"
dependencies:
  bloc: ^8.0.0

执行dart pub get 下载库

PS C:\Users\XXX\Desktop\blocTest> dart pub get
Resolving dependencies...
Got dependencies!

开始上手

这是偷来官网的图:
在这里插入图片描述

状态是从 Cubit 中输出的,代表应用程序状态的一部分。可以通知 UI 组件状态,并根据当前状态重绘其自身的某些部分。

  1. 创建一个Cubit 类型
// 定义了要管理的状态类型,此处以int示例,复杂业务可以自定义类
class CounterCubit extends Cubit<int> {
  //CounterCubit() : super(0);//指定初始状态为0
  //也可以外部传入初始值:
  CounterCubit(int initialState) : super(initialState);
}
  1. 定义一个CounterCubit
final cubitA = CounterCubit(0); // state starts at 0
final cubitB = CounterCubit(10); // state starts at 10
  1. 添加输出状态的能力
class CounterCubit extends Cubit<int> {
  CounterCubit() : super(0);
  void increment() => emit(state + 1);
  //emit只能在 Cubit 内部使用。state是当前状态
}
  1. 使用
import 'package:bloc/bloc.dart';
void main() {
  final cubit = CounterCubit();
  print(cubit.state); // 0
  cubit.increment();
  print(cubit.state); // 1
  cubit.close();
}
  1. 订阅

实际上CubitStream 的一种特殊类型,可以通过订阅来更新其状态

void myPrint(int data)  {
  print(data);
}

Future<void> main() async {
  final cubit = CounterCubit();
  final subscription = cubit.stream.listen(myPrint); // 1
  cubit.increment(); //输出1
  await Future.delayed(Duration.zero);
  cubit.increment();//输出2

  await Future.delayed(Duration.zero);
  await subscription.cancel();
  await cubit.close();
}
  1. 观察

可以通过添加onChange函数来观察Cubit的变化

class CounterCubit extends Cubit<int> {
  CounterCubit() : super(0);

  void increment() => emit(state + 1);

  @override
  void onChange(Change<int> change) {
    super.onChange(change);
    print(change);
  }
}

修改main函数:

void main() {
  CounterCubit()
    ..increment()
    ..increment()
    ..close();
}

输出结果:

Change { currentState: 0, nextState: 1 }
Change { currentState: 1, nextState: 2 }

可见输出了当前状态和下一次状态

  1. 使用BlocObserver
    添加一个一个Observer:
class SimpleBlocObserver extends BlocObserver {
  @override
  void onChange(BlocBase bloc, Change change) {
    super.onChange(bloc, change);
    print('${bloc.runtimeType} $change');
    print(bloc.state);//访问Cuit实例状态
  }
}

修改main函数:

void main() {
  BlocOverrides.runZoned(
    () {
      CounterCubit()
        ..increment()
        ..close();
    },
    blocObserver: SimpleBlocObserver(),
  );
}

上面的代码在调用CounterCubit.increment()后会依次调用CounterCubit本身的onChangeSimpleBlocObserveronChange,其实在BlocObserver 中也可以访问Cubit实例(bloc变量)

  1. 错误处理

再次修改代码,人为在在increment()函数里面调用addError制造错误,此时会调用CubitonError方法进行错误处理

class CounterCubit extends Cubit<int> {
  CounterCubit() : super(0);

  void increment() {
    addError(Exception('increment error!'), StackTrace.current);
    emit(state + 1);
  }

  @override
  void onChange(Change<int> change) {
    super.onChange(change);
    print(change);
  }

  @override
  void onError(Object error, StackTrace stackTrace) {
    print('$error, $stackTrace');
    super.onError(error, stackTrace);
  }
}

此时运行的话就会报错了

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值