Flutter状态管理架构插件ilgiz_bloc的使用
Flutter状态管理架构插件ilgiz_bloc的使用
使用 #
让我们看看如何使用BlocProvider为CounterPage提供一个CounterCubit,并通过BlocBuilder响应状态变化。
counter_cubit.dart #
class CounterCubit extends Cubit<int> {
CounterCubit() : super(0);
void increment() => emit(state + 1);
void decrement() => emit(state - 1);
}
main.dart #
void main() => runApp(CounterApp());
class CounterApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: BlocProvider(
create: (_) => CounterCubit(),
child: CounterPage(),
),
);
}
}
counter_page.dart #
class CounterPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Counter')),
body: BlocBuilder<CounterCubit, int>(
builder: (context, count) => Center(child: Text('$count')),
),
floatingActionButton: Column(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
FloatingActionButton(
child: const Icon(Icons.add),
onPressed: () => context.read<CounterCubit>().increment(),
),
const SizedBox(height: 4),
FloatingActionButton(
child: const Icon(Icons.remove),
onPressed: () => context.read<CounterCubit>().decrement(),
),
],
),
);
}
}
此时,我们已经成功将展示层与业务逻辑层分离。注意CounterPage小部件对用户点击按钮时发生的情况一无所知。该小部件只是通知CounterCubit用户按下了增加或减少按钮。
Bloc Widgets #
BlocBuilder #
BlocBuilder 是一个 Flutter 小部件,它需要一个bloc和一个builder函数。BlocBuilder会根据新的状态构建小部件。BlocBuilder类似于StreamBuilder,但具有更简单的 API 来减少样板代码的数量。builder 函数可能会被调用多次,并且应该是一个纯函数,根据状态返回一个 widget。
如果需要在状态变化时执行某些操作(如导航、显示对话框等),请查看BlocListener。
如果省略了bloc参数,BlocBuilder将自动通过BlocProvider和当前的BuildContext进行查找。
BlocBuilder<BlocA, BlocAState>(
builder: (context, state) {
// 根据 BlocA 的状态返回小部件
}
)
仅当需要提供一个作用域限于单个小部件且无法通过父级BlocProvider和当前BuildContext访问的小部件时,才指定bloc。
BlocBuilder<BlocA, BlocAState>(
bloc: blocA, // 提供本地 bloc 实例
builder: (context, state) {
// 根据 BlocA 的状态返回小部件
}
)
为了对builder函数的调用进行细粒度控制,可以提供可选的buildWhen。buildWhen接受前一个 bloc 状态和当前 bloc 状态并返回一个布尔值。如果buildWhen返回true,则builder将被调用并重新构建小部件;如果返回false,则不会调用builder,也不会重新构建小部件。
BlocBuilder<BlocA, BlocAState>(
buildWhen: (previousState, state) {
// 返回 true/false 以确定是否要基于状态重新构建小部件
},
builder: (context, state) {
// 根据 BlocA 的状态返回小部件
}
)
BlocSelector #
BlocSelector 是一个 Flutter 小部件,类似于BlocBuilder,但它允许开发者通过选择基于当前 bloc 状态的新值来过滤更新。如果所选值未发生变化,则可以防止不必要的构建。所选值必须是不可变的,以便BlocSelector能够准确地确定是否应再次调用builder。
如果省略了bloc参数,BlocSelector将自动通过BlocProvider和当前的BuildContext进行查找。
BlocSelector<BlocA, BlocAState, SelectedState>(
selector: (state) {
// 基于提供的状态返回所选状态。
},
builder: (context, state) {
// 基于所选状态返回小部件。
},
)
BlocProvider #
BlocProvider 是一个 Flutter 小部件,通过BlocProvider.of<T>(context)向其子项提供 bloc。它是作为依赖注入 (DI) 小部件使用的,以便为子树中的多个小部件提供单个 bloc 实例。
在大多数情况下,应该使用BlocProvider创建新的 bloc,这些 bloc 将可供子树中的其他部分使用。在这种情况下,由于BlocProvider负责创建 bloc,因此它将自动处理关闭。
BlocProvider(
create: (BuildContext context) => BlocA(),
child: ChildA(),
);
默认情况下,BlocProvider会懒加载 bloc,这意味着当通过BlocProvider.of<BlocA>(context)查找 bloc 时,才会执行create。
若要覆盖此行为并强制立即运行create,可以将lazy设置为false。
BlocProvider(
lazy: false,
create: (BuildContext context) => BlocA(),
child: ChildA(),
);
在某些情况下,可以使用BlocProvider向新的 widget 树部分提供现有的 bloc。这通常用于将现有 bloc 提供给新路由。在这种情况下,由于BlocProvider没有创建 bloc,因此不会自动关闭 bloc。
BlocProvider.value(
value: BlocProvider.of<BlocA>(context),
child: ScreenA(),
);
然后可以从ChildA或ScreenA检索BlocA:
// 使用扩展
context.read<BlocA>();
// 不使用扩展
BlocProvider.of<BlocA>(context);
上述片段导致一次查找,小部件不会收到更改的通知。要检索实例并订阅后续状态更改,请使用:
// 使用扩展
context.watch<BlocA>();
// 不使用扩展
BlocProvider.of<BlocA>(context, listen: true);
此外,还可以使用context.select来检索状态的一部分,并仅在所选部分发生变化时作出反应。
final isPositive = context.select((CounterBloc b) => b.state >= 0);
上述代码只有在CounterBloc的状态从正变为负或反之时才会重建,并且功能上等同于使用BlocSelector。
MultiBlocProvider #
MultiBlocProvider 是一个 Flutter 小部件,它可以将多个BlocProvider小部件合并为一个。
MultiBlocProvider 提高了可读性,并消除了嵌套多个BlocProvider的需要。
通过使用MultiBlocProvider,我们可以从:
BlocProvider<BlocA>(
create: (BuildContext context) => BlocA(),
child: BlocProvider<BlocB>(
create: (BuildContext context) => BlocB(),
child: BlocProvider<BlocC>(
create: (BuildContext context) => BlocC(),
child: ChildA(),
)
)
)
转换为:
MultiBlocProvider(
providers: [
BlocProvider<BlocA>(
create: (BuildContext context) => BlocA(),
),
BlocProvider<BlocB>(
create: (BuildContext context) => BlocB(),
),
BlocProvider<BlocC>(
create: (BuildContext context) => BlocC(),
),
],
child: ChildA(),
)
BlocListener #
BlocListener 是一个 Flutter 小部件,它接受一个BlocWidgetListener和一个可选的bloc,并在 bloc 的状态变化时调用listener。它应该用于需要在每次状态变化时发生的功能,例如导航、显示SnackBar、显示Dialog等。
listener对于每个状态变化只调用一次(不包括初始状态),不像BlocBuilder中的builder,并且是一个void函数。
如果省略了bloc参数,BlocListener将自动通过BlocProvider和当前的BuildContext进行查找。
BlocListener<BlocA, BlocAState>(
listener: (context, state) {
// 基于 BlocA 的状态执行操作
},
child: Container(),
)
仅当需要提供一个无法通过BlocProvider和当前BuildContext访问的 bloc 时,才指定bloc。
BlocListener<BlocA, BlocAState>(
bloc: blocA,
listener: (context, state) {
// 基于 BlocA 的状态执行操作
}
)
为了对listener函数的调用进行细粒度控制,可以提供可选的listenWhen。listenWhen接受前一个 bloc 状态和当前 bloc 状态并返回一个布尔值。如果listenWhen返回true,则listener将被调用;如果返回false,则不会调用listener。
BlocListener<BlocA, BlocAState>(
listenWhen: (previousState, state) {
// 返回 true/false 以确定是否调用 listener
},
listener: (context, state) {
// 基于 BlocA 的状态执行操作
},
child: Container(),
)
MultiBlocListener #
MultiBlocListener 是一个 Flutter 小部件,它可以将多个BlocListener小部件合并为一个。
MultiBlocListener 提高了可读性,并消除了嵌套多个BlocListener的需要。
通过使用MultiBlocListener,我们可以从:
BlocListener<BlocA, BlocAState>(
listener: (context, state) {},
child: BlocListener<BlocB, BlocBState>(
listener: (context, state) {},
child: BlocListener<BlocC, BlocCState>(
listener: (context, state) {},
child: ChildA(),
),
),
)
转换为:
MultiBlocListener(
listeners: [
BlocListener<BlocA, BlocAState>(
listener: (context, state) {},
),
BlocListener<BlocB, BlocBState>(
listener: (context, state) {},
),
BlocListener<BlocC, BlocCState>(
listener: (context, state) {},
),
],
child: ChildA(),
)
BlocConsumer #
BlocConsumer 暴露了builder和listener,以便响应新的状态。BlocConsumer类似于嵌套的BlocListener和BlocBuilder,但减少了样板代码的数量。BlocConsumer应该只在需要同时重建 UI 并对 bloc 的状态变化执行其他反应时使用。BlocConsumer需要一个必需的BlocWidgetBuilder和BlocWidgetListener,以及可选的bloc、BlocBuilderCondition和BlocListenerCondition。
如果省略了bloc参数,BlocConsumer将自动通过BlocProvider和当前的BuildContext进行查找。
BlocConsumer<BlocA, BlocAState>(
listener: (context, state) {
// 基于 BlocA 的状态执行操作
},
builder: (context, state) {
// 根据 BlocA 的状态返回小部件
}
)
可以实现可选的listenWhen和buildWhen来进行更精细的控制,以决定何时调用listener和builder。listenWhen和buildWhen将在每次bloc状态变化时被调用。它们各自接受前一个state和当前state,并必须返回一个bool,以确定是否调用builder和/或listener函数。前一个state将在BlocConsumer初始化时设置为bloc的当前state。listenWhen和buildWhen是可选的,如果没有实现,它们将默认为true。
BlocConsumer<BlocA, BlocAState>(
listenWhen: (previous, current) {
// 返回 true/false 以确定是否调用 listener
},
listener: (context, state) {
// 基于 BlocA 的状态执行操作
},
buildWhen: (previous, current) {
// 返回 true/false 以确定是否重建小部件
},
builder: (context, state) {
// 根据 BlocA 的状态返回小部件
}
)
RepositoryProvider #
RepositoryProvider 是一个 Flutter 小部件,它通过RepositoryProvider.of<T>(context)向其子项提供 repository。它是作为依赖注入 (DI) 小部件使用的,以便为子树中的多个小部件提供单个 repository 实例。BlocProvider应该用于提供 bloc,而RepositoryProvider应该仅用于 repository。
RepositoryProvider(
create: (context) => RepositoryA(),
child: ChildA(),
);
然后可以从ChildA检索Repository实例:
// 使用扩展
context.read<RepositoryA>();
// 不使用扩展
RepositoryProvider.of<RepositoryA>(context)
MultiRepositoryProvider #
MultiRepositoryProvider 是一个 Flutter 小部件,它可以将多个RepositoryProvider小部件合并为一个。
MultiRepositoryProvider 提高了可读性,并消除了嵌套多个RepositoryProvider的需要。
通过使用MultiRepositoryProvider,我们可以从:
RepositoryProvider<RepositoryA>(
create: (context) => RepositoryA(),
child: RepositoryProvider<RepositoryB>(
create: (context) => RepositoryB(),
child: RepositoryProvider<RepositoryC>(
create: (context) => RepositoryC(),
child: ChildA(),
)
)
)
转换为:
MultiRepositoryProvider(
providers: [
RepositoryProvider<RepositoryA>(
create: (context) => RepositoryA(),
),
RepositoryProvider<RepositoryB>(
create: (context) => RepositoryB(),
),
RepositoryProvider<RepositoryC>(
create: (context) => RepositoryC(),
),
],
child: ChildA(),
)
更多关于Flutter状态管理架构插件ilgiz_bloc的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter状态管理架构插件ilgiz_bloc的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
ilgiz_bloc 是一个基于 flutter_bloc 的状态管理插件,旨在简化 Bloc 模式的使用并提供更简洁的 API。以下是如何使用 ilgiz_bloc 的基本指南。
1. 添加依赖
首先,在 pubspec.yaml 文件中添加 ilgiz_bloc 依赖:
dependencies:
flutter:
sdk: flutter
ilgiz_bloc: ^1.0.0 # 请使用最新版本
然后运行 flutter pub get 来安装依赖。
2. 创建 Bloc
使用 ilgiz_bloc 创建 Bloc 非常简单。以下是一个简单的计数器示例:
import 'package:ilgiz_bloc/ilgiz_bloc.dart';
class CounterBloc extends Bloc<CounterEvent, int> {
CounterBloc() : super(0);
[@override](/user/override)
Stream<int> mapEventToState(CounterEvent event) async* {
if (event is IncrementEvent) {
yield state + 1;
} else if (event is DecrementEvent) {
yield state - 1;
}
}
}
abstract class CounterEvent {}
class IncrementEvent extends CounterEvent {}
class DecrementEvent extends CounterEvent {}
3. 使用 BlocBuilder 和 BlocProvider
在 Flutter 应用中使用 BlocProvider 和 BlocBuilder 来管理状态:
import 'package:flutter/material.dart';
import 'package:ilgiz_bloc/ilgiz_bloc.dart';
import 'counter_bloc.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
home: BlocProvider(
create: (context) => CounterBloc(),
child: CounterPage(),
),
);
}
}
class CounterPage extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
final CounterBloc counterBloc = BlocProvider.of<CounterBloc>(context);
return Scaffold(
appBar: AppBar(title: Text('Counter App')),
body: Center(
child: BlocBuilder<CounterBloc, int>(
builder: (context, count) {
return Text('Count: $count', style: TextStyle(fontSize: 24));
},
),
),
floatingActionButton: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
FloatingActionButton(
onPressed: () => counterBloc.add(IncrementEvent()),
child: Icon(Icons.add),
),
SizedBox(height: 10),
FloatingActionButton(
onPressed: () => counterBloc.add(DecrementEvent()),
child: Icon(Icons.remove),
),
],
),
);
}
}

