Flutter 86: 初识状态管理 Bloc (一)

简介: 0 基础学习 Flutter,第八十六步:简单了解 Bloc 状态管理 (一)!

      小菜以前尝试过 provider 状态管理工具,简单便捷;但在新的项目中,相关同学采用的是 Bloc 状态管理工具,且前段时间何时简单了解了 Stream 相关知识,因此趁机学习一下基本的 Bloc 相关的内容;

Bloc

      Bloc 可以方便的把样式与业务逻辑区分开,从而使开发更便捷,可重用性更好,测试也更加方便;

      在使用 Bloc 之前需要提前了解一下如下几个概念;

Event

      Event 事件作为 Bloc 的输入,一般是为了响应用户交互(例如按钮按下)或生命周期事件(例如页面加载)而添加它们。可以使用枚举类型定义事件类,对于相对复杂的事件可以联合业务定义为 class

enum TestEvent { onEvent1, onEvent2 ... onEventN}

States

      States 状态作为 Bloc 的输出,一般用于 UI 状态的更新,页面更新绘制等;一般需要定义不同的数据类型来表示数据状态的变更;

class TestState {
    final int state1;
    final String state2;
    ...
    final User stateN;
    
    TestState(this.state1, this.state2 ... this.stateN);
}

Transitions

      Transitions 转场作为从一个状态到下一个状态的过度,过渡由当前状态,事件和下一个状态组成;例如小菜上述定义的 TestEvent 中的各个 onEvent 中状态变更等均可以视为 Transitions 转场;onTransitionBlocstate 更新之前被调用,常用于记录 Bloc 日志和分析;

@override
void onTransition(Transition<NumberEvent, int> transition) {
  print('====onTransition===${transition}');
  super.onTransition(transition);
}

Streams

      作为异步数据传输;其中使用 async* 时可以使用 yield 关键字并返回一个 Stream 数据;

Stream<int> testStream(int max) async* {
    for (int i = 0; i < max; i++) {
        yield i;
    }
}

Blocs

      Bloc 作为将 Stream 输入的 Event 事件转换为输出的 States 状态;每个自定义的 Bloc 必须继承自基础的 Bloc;通过复写 initialStatemapEventToState 方法来完成事件 EventState 状态的转换;
      initialStateBloc 初始化状态,该状态是接收任何事件之前的状态;
      mapEventToStateEvent 作为参数,返回的是 Streamstate 状态,通过 state 属性随时访问当前的块状态;
      每个 Bloc 都有一个 add 方法,用来添加新的 EventmapEventToState 中;
      Bloc 通过 onError 方法获取异常信息并处理等;

class TestBloc extends Bloc<TestEvent, int> {
  @override
  int get initialState => 0;

  @override
  Stream<int> mapEventToState(TestEvent event) async* {
    switch (event) {
      case TestEvent.onEvent1:
        yield state - 1;
        break;
      case TestEvent.onEvent2:
        yield state + 1;
        break;
    }
  }
  
  @override
  void onError(Object error, StackTrace stackTrace) {
    print('====onError===$error, $stackTrace');
    super.onError(error, stackTrace);
  }
}

BlocDelegate

      BlocDelegateBloc 的委托,可以在全局或需要的作用域范围内统一管理 onTransitiononError 等;

class NumberBlocDelegate extends BlocDelegate {
  @override
  void onEvent(Bloc bloc, Object event) {
    print('====Delegate.onEvent===$bloc====$event');
    super.onEvent(bloc, event);
  }

  @override
  void onTransition(Bloc bloc, Transition transition) {
    print('====Delegate.onTransition===$bloc====$transition');
    super.onTransition(bloc, transition);
  }

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

TestCode

      小菜尝试了最简单的 Bloc,点击按钮会数字会递增,目前更新 UI 是通过 setState() 方式更新数据,在下一节中会尝试用 FlutterBloc 方式进行数据更新;

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

class BlocPage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => _BlocPageState();
}

class _BlocPageState extends State<BlocPage> {
  var _number = 0;
  NumberBloc _bloc = NumberBloc();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(title: Text('Bloc Page')),
        body: Center(
            child: Text('当前 Number = $_number\n下次 Number = ${_bloc.state}',
                style: TextStyle(fontSize: 20.0, color: Colors.blue))),
        floatingActionButton: FloatingActionButton(
            child: Icon(Icons.add),
            onPressed: () {
              _bloc.add(NumberEvent.addEvent);
              setState(() => _number = _bloc.state);
            }));
  }
}

enum NumberEvent { addEvent }

class NumberBloc extends Bloc<NumberEvent, int> {
  @override
  int get initialState => 10;

  @override
  Stream<int> mapEventToState(NumberEvent event) async* {
    switch (event) {
      case NumberEvent.addEvent:
        yield state + 5;
        break;
    }
  }

  @override
  void onTransition(Transition<NumberEvent, int> transition) {
    print('====onTransition===${transition}');
    super.onTransition(transition);
  }

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

      小菜初步体验了 Bloc,初步感觉比 Provider 稍微复杂一些,但是分工更为明确;而小菜对 Bloc 的 应用还不够熟练,下一节重点尝试 FlutterBloc 对于 UI 的数据更新等;如有错误,请多多指导!

来源: 阿策小和尚

目录
相关文章
|
13天前
|
存储 Shell 开发工具
Flutter&鸿蒙next 中使用 MobX 进行状态管理
本文介绍了如何在 Flutter 中使用 MobX 进行状态管理。MobX 是一个基于观察者模式的响应式编程库,通过 `@observable` 和 `@action` 注解管理状态,并使用 `Observer` 小部件自动更新 UI。文章详细讲解了 MobX 的核心概念、如何集成到 Flutter 项目中以及具体的代码示例。适合希望在 Flutter 应用中实现高效状态管理的开发者阅读。
86 9
|
13天前
|
存储 开发者
Flutter&鸿蒙next 使用 BLoC 模式进行状态管理详解
本文详细介绍了如何在 Flutter 中使用 BLoC 模式进行状态管理。BLoC 模式通过将业务逻辑与 UI 层分离,利用 Streams 和 Sinks 实现状态管理和 UI 更新,提高代码的可维护性和可测试性。文章涵盖了 BLoC 的基本概念、实现步骤及代码示例,包括定义 Event 和 State 类、创建 Bloc 类、提供 Bloc 实例以及通过 BlocBuilder 更新 UI。通过一个简单的计数器应用示例,展示了 BLoC 模式的具体应用和代码实现。
67 1
|
15天前
|
开发工具 开发者
Flutter&鸿蒙next 状态管理高级使用:深入探讨 Provider
本文深入探讨了 Flutter 中 Provider 的高级用法,涵盖多 Provider 组合、Selector 优化性能、ChangeNotifierProxyProvider 管理依赖关系以及自定义 Provider。通过这些技巧,开发者可以构建高效、可维护的响应式应用。
62 2
|
28天前
|
开发工具 开发者
Flutter&鸿蒙next 状态管理高级使用:深入探讨 Provider
Flutter&鸿蒙next 状态管理高级使用:深入探讨 Provider
|
13天前
|
缓存 JavaScript API
Flutter&鸿蒙next 状态管理框架对比分析
在 Flutter 开发中,状态管理至关重要,直接影响应用的性能和可维护性。本文对比分析了常见的状态管理框架,包括 setState()、InheritedWidget、Provider、Riverpod、Bloc 和 GetX,详细介绍了它们的优缺点及适用场景,并提供了 Provider 的示例代码。选择合适的状态管理框架需考虑应用复杂度、团队熟悉程度和性能要求。
81 0
|
28天前
【Flutter】状态管理:Provider状态管理
【Flutter】状态管理:Provider状态管理
14 0
|
1月前
|
UED
flutter:动画&状态管理 (十三)
本文档介绍了Flutter中`animatedList`的使用方法和状态管理的示例。`animatedList`用于创建带有动画效果的列表,示例代码展示了如何添加、删除列表项,并执行相应的动画效果。状态管理部分通过一个简单的点击切换颜色的示例,演示了如何在Flutter中管理组件的状态。
|
3月前
Flutter 状态管理新境界:多Provider并行驱动UI
Flutter 状态管理新境界:多Provider并行驱动UI
62 0
|
3月前
|
Dart API
状态管理的艺术:探索Flutter的Provider库
状态管理的艺术:探索Flutter的Provider库
48 0
|
4月前
|
容器
flutter 布局管理【详解】
flutter 布局管理【详解】
38 3