flutter之bloc使用详解

flutter中一切皆为Widget,因此在我们开发中,往往业务和UI逻辑写在一起,这样不利于代码维护,因此状态管理框架久诞生了,这篇就开始讲一讲Bloc。

对于Bloc库有两个,如下图:
flutter_bloc其实是对bloc的进一步封装,flutter_bloc引入了bloc库和provider库,是对bloc的进一步延伸。

bloc官方文档:https://bloclibrary.dev/#/zh-cn/coreconcepts

一.Bloc介绍

BLoC设计模式:BLoC模式的核心是Sink和Stream,它们用于处理输入和输出。通常,你会创建一个BLoC类,该类接收输入流并根据输入产生输出流。然后,UI组件订阅输出流以接收状态更新,并将用户操作发送到输入流。

Bloc有两种模式:

Bloc模式:该模式划分四层结构

bloc:逻辑层

state:数据层

event:所有的交互事件

view:页面

Cubit模式:该模式划分了三层结构

cubit:逻辑层

state:数据层

view:页面

Bloc模式和Cubit模式区别:

  • 复杂度: BLoC:BLoC通常用于管理更复杂的业务逻辑和状态。它可以处理多个事件和多个状态,适用于大型、复杂的应用程序。

    Cubit:Cubit的设计更简单,适用于处理较简单的状态和事件。它更适合于小型和中型应用程序,以及对状态管理模式不太熟悉的开发者。

  • 事件和状态管理: BLoC:在BLoC中,事件和状态是分开管理的,你需要自己编写事件和状态的类,并在BLoC中进行映射。这使得BLoC更加灵活,但也更加复杂。

    Cubit:Cubit将事件和状态合并到一个类中,称为Cubit类。这使得代码更加简洁,但在处理复杂的事件和状态时可能会变得混乱。

  • 异步支持: BLoC:BLoC天生支持异步操作,可以轻松处理异步任务,例如网络请求。这是因为BLoC的mapEventToState方法可以返回Stream。

    Cubit:Cubit也支持异步操作,但需要使用Emit函数来发射新的状态。

二.flutter_bloc简单使用

导入库:

dart 复制代码
flutter_bloc: ^8.1.3

这是一个插件,可选择使用,简化模版代码生成。安装flutter_bloc插件

使用案例:计数器

dart 复制代码
import 'package:flutter_bloc/flutter_bloc.dart';

// 定义事件
enum CounterEvent { increment, decrement }

class CounterBloc extends Bloc<CounterEvent, int> {
  CounterBloc() : super(0);

  @override
  Stream<int> mapEventToState(CounterEvent event) async* {
    switch (event) {
      case CounterEvent.increment:
        yield state + 1;
        break;
      case CounterEvent.decrement:
        yield state - 1;
        break;
    }
  }
}

在页面中使用 Bloc:

dart 复制代码
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

class CounterPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Counter App'),
      ),
      body: BlocProvider(
        create: (context) => CounterBloc(),
        child: CounterView(),
      ),
    );
  }
}

class CounterView extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final counterBloc = BlocProvider.of<CounterBloc>(context);

    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          BlocBuilder<CounterBloc, int>(
            builder: (context, count) {
              return Text('Count: $count', style: TextStyle(fontSize: 24));
            },
          ),
          SizedBox(height: 16),
          Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              FloatingActionButton(
                onPressed: () {
                  counterBloc.add(CounterEvent.increment);
                },
                child: Icon(Icons.add),
              ),
              SizedBox(width: 16),
              FloatingActionButton(
                onPressed: () {
                  counterBloc.add(CounterEvent.decrement);
                },
                child: Icon(Icons.remove),
              ),
            ],
          ),
        ],
      ),
    );
  }
}

三.各种小部件

BlocBuilder

dart 复制代码
BlocBuilder<BlocA, BlocAState>(
  builder: (context, state) {
    // return widget here based on BlocA's state
  }
)

BlocBuilder是一个 Flutter 小部件,需要一个bloc和 一个builder函数。BlocBuilder处理构建小部件以响应新状态。BlocBuilder与 非常相似,StreamBuilder但具有更简单的 API,以减少所需的样板代码量。该builder函数可能会被多次调用,并且应该是一个纯函数,它返回一个小部件以响应状态。

BlocSelector

dart 复制代码
BlocSelector<BlocA, BlocAState, SelectedState>(
  selector: (state) {
    // return selected state based on the provided state.
  },
  builder: (context, state) {
    // return widget here based on the selected state.
  },
)

BlocSelector是一个 Flutter 小部件,它类似于BlocBuilder但允许开发人员通过基于当前块状态选择新值来过滤更新。如果所选值不更改,则会阻止不必要的构建。所选值必须是不可变的,以便BlocSelector准确确定是否builder应该再次调用。

BlocListener

dart 复制代码
BlocListener<BlocA, BlocAState>(
  listener: (context, state) {
    // do stuff here based on BlocA's state
  },
  child: Container(),
)

BlocListener是一个 Flutter 小部件,它采用BlocWidgetListener和 一个可选参数bloc,并调用listener来响应块中的状态变化。它应该用于每次状态更改需要发生一次的功能,例如导航、显示 a SnackBar、显示 aDialog等...

相关推荐
AiFlutter11 小时前
Flutter之Package教程
flutter
Mingyueyixi15 小时前
Flutter Spacer引发的The ParentDataWidget Expanded(flex: 1) 惨案
前端·flutter
crasowas1 天前
Flutter问题记录 - 适配Xcode 16和iOS 18
flutter·ios·xcode
老田低代码2 天前
Dart自从引入null check后写Flutter App总有一种难受的感觉
前端·flutter
AiFlutter2 天前
Flutter Web首次加载时添加动画
前端·flutter
ZemanZhang4 天前
Flutter启动无法运行热重载
flutter
AiFlutter4 天前
Flutter-底部选择弹窗(showModalBottomSheet)
flutter
帅次4 天前
Android Studio:驱动高效开发的全方位智能平台
android·ide·flutter·kotlin·gradle·android studio·android jetpack
程序者王大川5 天前
【前端】Flutter vs uni-app:性能对比分析
前端·flutter·uni-app·安卓·全栈·性能分析·原生
yang2952423615 天前
使用 Vue.js 将数据对象的值放入另一个数据对象中
前端·vue.js·flutter