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
库中的功能)的基本集成和使用。希望这个示例对你有所帮助!