Flutter状态管理插件bloc的使用

发布于 1周前 作者 wuwangju 来自 Flutter

Flutter状态管理插件bloc的使用

概览

BLoC(Business Logic Component)是一种设计模式,旨在将业务逻辑与用户界面分离。bloc库是一个用于实现BLoC模式的状态管理库,它使得在Flutter应用中管理状态变得更加简单和可预测。

更多详情请访问:bloclibrary.dev

主要特性

  • 易用性:通过简单的API即可实现复杂的状态管理。
  • 可测试性:由于业务逻辑与UI完全分离,因此可以轻松地对业务逻辑进行单元测试。
  • 灵活性:支持多种方式来管理和监听状态的变化。
  • 社区支持:活跃的社区和丰富的文档资源。

支持的包


Cubit

CubitBlocBase 的一个子类,它可以用来管理任何类型的状态。Cubit 需要一个初始状态,并且可以通过调用 emit 方法来改变状态。

创建一个Cubit

/// 一个管理整数状态的 CounterCubit
class CounterCubit extends Cubit<int> {
  /// CounterCubit 的初始状态为 0
  CounterCubit() : super(0);

  /// 当 increment 被调用时,通过 state 访问当前状态并通过 emit 发出新状态
  void increment() => emit(state + 1);
}

使用Cubit

void main() {
  // 创建 CounterCubit 实例
  final cubit = CounterCubit();

  // 访问 cubit 的状态
  print(cubit.state); // 输出: 0

  // 触发状态变化
  cubit.increment();

  // 再次访问新的状态
  print(cubit.state); // 输出: 1

  // 关闭 cubit
  cubit.close();
}

监听Cubit

你可以通过覆盖 onChange 或者设置全局的 BlocObserver 来监听所有 Cubit 的变化。

class MyBlocObserver extends BlocObserver {
  @override
  void onChange(BlocBase bloc, Change change) {
    super.onChange(bloc, change);
    print('onChange -- ${bloc.runtimeType}, $change');
  }
}

void main() {
  Bloc.observer = MyBlocObserver();
  // 使用 cubits...
}

Bloc

Bloc 是一种更高级的状态管理工具,它依赖于事件触发状态变化。每个 Bloc 可以处理特定类型的事件,并根据这些事件转换成对应的状态。

创建一个Bloc

/// 定义 CounterBloc 处理的事件
sealed class CounterEvent {}

/// 通知 Bloc 增加计数器
final class CounterIncrementPressed extends CounterEvent {}

/// 一个处理 CounterEvent 并将其转换为 int 状态的 CounterBloc
class CounterBloc extends Bloc<CounterEvent, int> {
  /// CounterBloc 的初始状态为 0
  CounterBloc() : super(0) {
    // 注册事件处理器
    on<CounterIncrementPressed>((event, emit) => emit(state + 1));
  }
}

使用Bloc

Future<void> main() async {
  // 创建 CounterBloc 实例
  final bloc = CounterBloc();

  // 访问 bloc 的状态
  print(bloc.state); // 输出: 0

  // 添加事件以触发状态变化
  bloc.add(CounterIncrementPressed());

  // 确保事件已处理完毕
  await Future.delayed(Duration.zero);

  // 访问新的状态
  print(bloc.state); // 输出: 1

  // 关闭 bloc
  await bloc.close();
}

监听Bloc

除了 onChangeonError,你还可以覆盖 onEventonTransition 来监听事件和状态转换。

class CounterBloc extends Bloc<CounterEvent, int> {
  CounterBloc() : super(0) {
    on<CounterIncrementPressed>((event, emit) => emit(state + 1));
  }

  @override
  void onEvent(CounterEvent event) {
    super.onEvent(event);
    print(event);
  }

  @override
  void onTransition(Transition<CounterEvent, int> transition) {
    super.onTransition(transition);
    print(transition);
  }
}

示例代码

以下是一个完整的示例程序,展示了如何结合使用 SimpleBlocObserverCounterCubitCounterBloc

import 'dart:async';
import 'package:bloc/bloc.dart';

class SimpleBlocObserver extends BlocObserver {
  const SimpleBlocObserver();

  @override
  void onCreate(BlocBase<dynamic> bloc) {
    super.onCreate(bloc);
    print('onCreate -- bloc: ${bloc.runtimeType}');
  }

  @override
  void onEvent(Bloc<dynamic, dynamic> bloc, Object? event) {
    super.onEvent(bloc, event);
    print('onEvent -- bloc: ${bloc.runtimeType}, event: $event');
  }

  @override
  void onChange(BlocBase<dynamic> bloc, Change<dynamic> change) {
    super.onChange(bloc, change);
    print('onChange -- bloc: ${bloc.runtimeType}, change: $change');
  }

  @override
  void onTransition(
    Bloc<dynamic, dynamic> bloc,
    Transition<dynamic, dynamic> transition,
  ) {
    super.onTransition(bloc, transition);
    print('onTransition -- bloc: ${bloc.runtimeType}, transition: $transition');
  }

  @override
  void onError(BlocBase<dynamic> bloc, Object error, StackTrace stackTrace) {
    print('onError -- bloc: ${bloc.runtimeType}, error: $error');
    super.onError(bloc, error, stackTrace);
  }

  @override
  void onClose(BlocBase<dynamic> bloc) {
    super.onClose(bloc);
    print('onClose -- bloc: ${bloc.runtimeType}');
  }
}

void main() {
  Bloc.observer = const SimpleBlocObserver();
  cubitMain();
  blocMain();
}

void cubitMain() {
  print('----------CUBIT----------');

  /// Create a `CounterCubit` instance.
  final cubit = CounterCubit();

  /// Access the state of the `cubit` via `state`.
  print(cubit.state); // 0

  /// Interact with the `cubit` to trigger `state` changes.
  cubit.increment();

  /// Access the new `state`.
  print(cubit.state); // 1

  /// Close the `cubit` when it is no longer needed.
  cubit.close();
}

Future<void> blocMain() async {
  print('----------BLOC----------');

  /// Create a `CounterBloc` instance.
  final bloc = CounterBloc();

  /// Access the state of the `bloc` via `state`.
  print(bloc.state);

  /// Interact with the `bloc` to trigger `state` changes.
  bloc.add(CounterIncrementPressed());

  /// Wait for next iteration of the event-loop
  /// to ensure event has been processed.
  await Future<void>.delayed(Duration.zero);

  /// Access the new `state`.
  print(bloc.state);

  /// Close the `bloc` when it is no longer needed.
  await bloc.close();
}

/// A `CounterCubit` which manages an `int` as its state.
class CounterCubit extends Cubit<int> {
  /// The initial state of the `CounterCubit` is 0.
  CounterCubit() : super(0);

  /// When increment is called, the current state
  /// of the cubit is accessed via `state` and
  /// a new `state` is emitted via `emit`.
  void increment() => emit(state + 1);
}

/// The events which `CounterBloc` will react to.
abstract class CounterEvent {}

/// Notifies bloc to increment state.
class CounterIncrementPressed extends CounterEvent {}

/// A `CounterBloc` which handles converting `CounterEvent`s into `int`s.
class CounterBloc extends Bloc<CounterEvent, int> {
  /// The initial state of the `CounterBloc` is 0.
  CounterBloc() : super(0) {
    /// When a `CounterIncrementPressed` event is added,
    /// the current `state` of the bloc is accessed via the `state` property
    /// and a new state is emitted via `emit`.
    on<CounterIncrementPressed>((event, emit) => emit(state + 1));
  }
}

以上代码演示了如何在Flutter项目中使用 bloc 库来管理应用程序的状态。无论是简单的计数器功能还是更复杂的业务逻辑,都可以借助此库实现高效且易于维护的状态管理方案。


更多关于Flutter状态管理插件bloc的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter状态管理插件bloc的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,下面是一个关于如何在Flutter中使用Bloc状态管理插件的示例代码。Bloc是一个流行的状态管理库,特别适用于Flutter应用。

1. 添加依赖

首先,在你的pubspec.yaml文件中添加Bloc库的依赖:

dependencies:
  flutter:
    sdk: flutter
  bloc: ^8.0.0  # 确保使用最新版本
  flutter_bloc: ^8.0.0  # 确保使用最新版本

然后运行flutter pub get来安装依赖。

2. 创建Bloc和事件

假设我们有一个简单的计数器应用,首先创建一个事件类和一个状态类。

events.dart

import 'package:flutter_bloc/flutter_bloc.dart';

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

states.dart

import 'package:flutter_bloc/flutter_bloc.dart';

// 定义状态
class CounterState extends Equatable {
  final int count;

  const CounterState(this.count);

  @override
  List<Object?> get props => [count];
}

3. 创建Bloc

接下来,我们创建一个Bloc来处理事件并更新状态。

counter_bloc.dart

import 'package:bloc/bloc.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'events.dart';
import 'states.dart';

class CounterBloc extends Bloc<CounterEvent, CounterState> {
  CounterBloc() : super(CounterState(0)) {
    on<CounterEvent>((event, emit) {
      if (event == CounterEvent.increment) {
        emit(state.copyWith(count: state.count + 1));
      } else if (event == CounterEvent.decrement) {
        emit(state.copyWith(count: state.count - 1));
      }
    });
  }

  // Helper method to create a new state with updated count
  CounterState copyWith(int count) => CounterState(count);
}

4. 在UI中使用Bloc

最后,我们在UI组件中使用BlocBuilder来监听Bloc的状态并触发事件。

main.dart

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'counter_bloc.dart';
import 'states.dart';
import 'events.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: BlocProvider(
        create: (context) => CounterBloc(),
        child: CounterPage(),
      ),
    );
  }
}

class CounterPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Counter App')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            BlocBuilder<CounterBloc, CounterState>(
              builder: (context, state) {
                return Text(
                  'Count: ${state.count}',
                  style: Theme.of(context).textTheme.headline4,
                );
              },
            ),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: () => context.read<CounterBloc>().add(CounterEvent.increment),
              child: Text('Increment'),
            ),
            SizedBox(height: 10),
            ElevatedButton(
              onPressed: () => context.read<CounterBloc>().add(CounterEvent.decrement),
              child: Text('Decrement'),
            ),
          ],
        ),
      ),
    );
  }
}

5. 运行应用

现在你可以运行你的Flutter应用,应该会看到一个简单的计数器界面,你可以通过点击按钮来增加或减少计数。

这个示例展示了如何在Flutter中使用Bloc进行状态管理,包括定义事件和状态、创建Bloc逻辑以及在UI中监听和触发事件。希望这对你有所帮助!

回到顶部