Flutter UI组件集成插件bloc_widgets的使用
Flutter UI组件集成插件bloc_widgets的使用
bloc_widgets 是一个用于简化 Flutter 中 flutter_bloc 包使用的插件。它通过扩展 StatelessWidget 并覆盖 build 方法来提供一个名为 buildWithBloc 的方法,该方法用于根据给定的状态构建小部件。
BlocConsumerWidget 还提供了 listenWhen、buildWhen 和 listen 方法,这些方法与 BlocConsumer 相同。BlocBuilderWidget 提供了 buildWhen 方法,与 BlocBuilder 相同。BlocListenerWidget 提供了 listenWhen 方法,与 BlocListener 相同。SelectorWidget 提供了 selector 方法,与 BlocSelector 相同。
这些小部件支持 Bloc 和 Cubit。
特性
- 将
BlocConsumer功能封装到BlocConsumerWidget中。 - 将
BlocBuilder功能封装到BlocBuilderWidget中。 - 将
BlocListener功能封装到BlocListenerWidget中。 - 将
BlocSelector功能封装到BlocSelectorWidget中。
安装
在你的 pubspec.yaml 文件中添加 bloc_widgets 作为依赖:
dependencies:
bloc_widgets: ^1.1.2
示例代码
以下是一个完整的示例,展示了如何使用 bloc_widgets 插件中的不同小部件。
import 'package:bloc_widgets/bloc_widgets.dart';
import 'package:flutter/material.dart';
import 'calculator_bloc.dart';
import 'calculator_cubit.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(primarySwatch: Colors.blue),
// home: const MyHomePage(title: 'BlocWidget Demo'),
home: const MySelectorHomePage(title: 'BlocSelectorWidget Demo'),
);
}
}
class MyConsumerHomePage extends BlocConsumerWidget<CalculatorBloc, BlocState> {
const MyConsumerHomePage({super.key, required this.title});
final String title;
[@override](/user/override)
CalculatorBloc bloc(BuildContext context) => CalculatorBloc();
[@override](/user/override)
void onMount(CalculatorBloc bloc) => bloc.add(CalculatorEvent.onMount);
[@override](/user/override)
void listener(context, bloc, state) {
ScaffoldMessenger.of(context).clearSnackBars();
if (state.counter == 0) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Counter cleared')),
);
return;
}
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Counter changed')),
);
}
[@override](/user/override)
Widget build(context, bloc, state) {
final textTheme = Theme.of(context).textTheme;
return Scaffold(
appBar: AppBar(title: Text(title)),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text('Counter value:'),
Text('${state.counter}', style: textTheme.headlineMedium),
],
),
),
bottomNavigationBar: Padding(
padding: const EdgeInsets.all(16.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
FloatingActionButton(
onPressed: () => bloc.add(CalculatorEvent.remove),
tooltip: 'Decrement',
child: const Icon(Icons.exposure_minus_1),
),
TextButton(
onPressed: () => bloc.add(CalculatorEvent.clear),
child: const Text('Clear counter'),
),
FloatingActionButton(
onPressed: () => bloc.add(CalculatorEvent.add),
tooltip: 'Increment',
child: const Icon(Icons.exposure_plus_1),
),
],
),
),
);
}
}
class MyBuilderHomePage extends BlocBuilderWidget<CalculatorBloc, BlocState> {
const MyBuilderHomePage({super.key, required this.title});
final String title;
[@override](/user/override)
CalculatorBloc bloc(BuildContext context) => CalculatorBloc();
[@override](/user/override)
void onMount(CalculatorBloc bloc) => bloc.add(CalculatorEvent.onMount);
[@override](/user/override)
Widget build(context, bloc, state) {
final textTheme = Theme.of(context).textTheme;
return Scaffold(
appBar: AppBar(title: Text(title)),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text('Counter value:'),
Text('${state.counter}', style: textTheme.headlineMedium),
],
),
),
bottomNavigationBar: Padding(
padding: const EdgeInsets.all(16.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
FloatingActionButton(
onPressed: () => bloc.add(CalculatorEvent.remove),
tooltip: 'Decrement',
child: const Icon(Icons.exposure_minus_1),
),
TextButton(
onPressed: () => bloc.add(CalculatorEvent.clear),
child: const Text('Clear counter'),
),
FloatingActionButton(
onPressed: () => bloc.add(CalculatorEvent.add),
tooltip: 'Increment',
child: const Icon(Icons.exposure_plus_1),
),
],
),
),
);
}
}
class MySelectorHomePage extends BlocSelectorWidget<CalculatorCubit, CubitState, int> {
const MySelectorHomePage({super.key, required this.title});
final String title;
[@override](/user/override)
CalculatorCubit bloc(BuildContext context) => CalculatorCubit();
[@override](/user/override)
void onMount(CalculatorCubit bloc) => bloc.changeCounter(-1);
[@override](/user/override)
int selector(CubitState state) => state.counter;
[@override](/user/override)
Widget build(context, bloc, selector) {
final textTheme = Theme.of(context).textTheme;
return Scaffold(
appBar: AppBar(title: Text(title)),
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const Text('Counter value:'),
Text('$selector', style: textTheme.headlineMedium),
],
),
),
bottomNavigationBar: Padding(
padding: const EdgeInsets.all(16.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
FloatingActionButton(
onPressed: () => bloc.changeCounter(selector - 1),
tooltip: 'Decrement',
child: const Icon(Icons.exposure_minus_1),
),
TextButton(
onPressed: () => bloc.changeCounter(0),
child: const Text('Clear counter'),
),
FloatingActionButton(
onPressed: () => bloc.changeCounter(selector + 1),
tooltip: 'Increment',
child: const Icon(Icons.exposure_plus_1),
),
],
),
),
);
}
}
class MyListenerHomePage extends BlocListenerWidget<CalculatorCubit, CubitState> {
const MyListenerHomePage({super.key, required this.title});
final String title;
[@override](/user/override)
CalculatorCubit bloc(BuildContext context) => CalculatorCubit();
[@override](/user/override)
void onMount(CalculatorCubit bloc) => bloc.changeCounter(-1);
[@override](/user/override)
void listener(BuildContext context, CalculatorCubit bloc, CubitState state) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Counter value: ${state.counter}')),
);
}
[@override](/user/override)
Widget build(BuildContext context, CalculatorCubit bloc) {
return Scaffold(
appBar: AppBar(title: Text(title)),
body: const Center(child: Text('Click to show SnackBar with value')),
);
}
}
更多关于Flutter UI组件集成插件bloc_widgets的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter UI组件集成插件bloc_widgets的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何在Flutter项目中集成并使用bloc_widgets插件的示例代码。bloc_widgets插件主要用于简化Bloc状态管理与UI组件之间的集成。
首先,确保你已经在pubspec.yaml文件中添加了必要的依赖:
dependencies:
flutter:
sdk: flutter
flutter_bloc: ^8.0.0 # 确保版本是最新的
bloc: ^8.0.0 # 确保版本是最新的
然后,运行flutter pub get来获取这些依赖。
创建Bloc和State
接下来,我们创建一个简单的计数器Bloc和它的状态。
counter_bloc.dart
import 'package:bloc/bloc.dart';
part 'counter_event.dart';
part 'counter_state.dart';
class CounterBloc extends Bloc<CounterEvent, CounterState> {
CounterBloc() : super(CounterInitial());
@override
Stream<CounterState> mapEventToState(CounterEvent event) async* {
if (event is CounterIncremented) {
yield* _mapCounterIncrementedToState();
}
}
Stream<CounterState> _mapCounterIncrementedToState() async* {
yield CounterState(count: state.count + 1);
}
}
counter_event.dart
part of 'counter_bloc.dart';
abstract class CounterEvent {}
class CounterIncremented extends CounterEvent {}
counter_state.dart
part of 'counter_bloc.dart';
class CounterState {
final int count;
CounterState({required this.count});
@override
List<Object?> get props => [count];
}
class CounterInitial extends CounterState {
CounterInitial() : super(count: 0);
}
使用BlocProvider和BlocBuilder
现在,我们在UI组件中使用BlocProvider来提供Bloc实例,并使用BlocBuilder来根据Bloc状态更新UI。
main.dart
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'counter_bloc.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: BlocProvider(
create: (context) => CounterBloc(),
child: CounterPage(),
),
);
}
}
class CounterPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter Demo Home Page'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
BlocBuilder<CounterBloc, CounterState>(
builder: (context, state) {
return Text(
'${state.count}',
style: Theme.of(context).textTheme.headline4,
);
},
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
context.read<CounterBloc>().add(CounterIncremented());
},
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
解释
- Bloc和State: 我们定义了一个
CounterBloc,它处理CounterEvent并转换到CounterState。 - 事件和状态:
CounterEvent包含一个简单的事件CounterIncremented,CounterState包含一个整数count。 - UI组件: 在
main.dart中,我们使用BlocProvider来提供CounterBloc实例,并在CounterPage中使用BlocBuilder来监听状态变化并更新UI。 - 事件触发: 点击
FloatingActionButton时,触发CounterIncremented事件,从而更新Bloc状态。
这样,我们就完成了Flutter项目中bloc_widgets(实际上是flutter_bloc库中的功能)的基本集成和使用。希望这个示例对你有所帮助!

