Flutter复用逻辑块插件reusable_bloc_base的使用
Flutter复用逻辑块插件reusable_bloc_base的使用
reusable_bloc_base
轻量级扩展库,用于简化 flutter_bloc
的使用。
特性
覆盖了大多数常见的 Flutter BLoC 工作流程,避免了样板代码。
开始使用
安装该包:
flutter pub add reusable_bloc_base
使用方法
示例状态类
首先定义一个状态类 HelloWorldState
,继承自 BaseState
。
// Your state class
final class HelloWorldState extends BaseState<HelloWorldLoading> {
const HelloWorldState({
super.failure,
super.isLoading,
super.pendingActions,
super.success,
});
[@override](/user/override)
List<Object> get props => [
...super.props,
];
factory HelloWorldState.initial() {
return const HelloWorldState();
}
[@override](/user/override)
HelloWorldState copyWith({
AnySuccess? success,
AnyFailure? failure,
bool? isLoading,
Set<HelloWorldLoading>? pendingActions,
}) {
return HelloWorldState(
failure: failure ?? this.failure,
isLoading: isLoading ?? this.isLoading,
pendingActions: pendingActions ?? this.pendingActions,
success: success ?? this.success,
);
}
[@override](/user/override)
String toString() {
return '''
HelloWorldState {
failure: $failure,
isLoading: $isLoading,
pendingActions: $pendingActions,
success: $success,
}
''';
}
}
示例BLoC类
接下来定义一个 BLoC 类 HelloWorldBloc
,继承自 BaseBloc
。
// Your bloc class
class HelloWorldBloc extends BaseBloc<HelloWorldLoading, HelloWorldEvent, HelloWorldState> {
HelloWorldBloc() {
// Your initialization code
}
FutureOr<void> _onHelloWorldEvent(
HelloWorldEvent event,
Emitter<HelloWorldState> emit,
) async {
emit(state.beforeLoading()); // 设置 isLoading 为 true
try {
// Your business logic here ... (synchronous or asynchronous)
emit(state.successState<HelloWorldState>()); // 设置 isLoading 为 false 并设置成功状态
} catch (e, stack) {
addError(e, stack); // 设置失败状态,错误详情会反映在 state.failure 中
}
}
}
示例代码
以下是一个完整的示例代码,展示了如何使用 reusable_bloc_base
。
import 'package:example/bloc/counter_bloc.dart';
import 'package:example/widgets/loading_indicator.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:loader_overlay/loader_overlay.dart';
import 'package:reusable_bloc_base/reusable_bloc_base.dart';
import 'package:toastification/toastification.dart';
void main() {
// 初始化加载器
BlocStateReactor.showLoading = (context) => context.loaderOverlay.show();
BlocStateReactor.hideLoading = (context) => context.loaderOverlay.hide();
// 成功状态回调
BlocStateReactor.onSuccessState = (context, success) {
toastification.show(
context: context,
title: Text(success.translate()),
autoCloseDuration: const Duration(seconds: 3),
style: ToastificationStyle.minimal,
type: ToastificationType.success,
);
};
// 失败状态回调
BlocStateReactor.onErrorState = (context, failure) {
toastification.show(
context: context,
title: Text(failure.translate()),
autoCloseDuration: const Duration(seconds: 3),
style: ToastificationStyle.minimal,
type: ToastificationType.error,
);
};
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
[@override](/user/override)
Widget build(BuildContext context) {
return GlobalLoaderOverlay(
overlayWidgetBuilder: (_) {
return const LoadingIndicator();
},
overlayColor: Colors.black.withOpacity(0.4),
overlayHeight: MediaQuery.of(context).size.height,
overlayWidth: MediaQuery.of(context).size.width,
child: ToastificationWrapper(
child: MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: BlocProvider(
create: (context) => CounterBloc(),
child: const MyHomePage(title: 'Flutter Demo Home Page'),
),
),
),
);
}
}
class MyHomePage extends StatelessWidget {
const MyHomePage({super.key, required this.title});
final String title;
[@override](/user/override)
Widget build(BuildContext context) {
return BaseStateListener<void, CounterBloc, CounterState>(
child: Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'You have pushed the button this many times:',
),
BlocBuilder<CounterBloc, CounterState>(
builder: (context, state) {
return Text(
state.counter.toString(),
style: Theme.of(context).textTheme.headlineMedium,
);
},
),
ElevatedButton(
onPressed: () {
context.read<CounterBloc>().add(const IncrementCounterEvent());
},
child: const Text('Increment'),
),
const SizedBox(
height: 20,
),
ElevatedButton(
onPressed: () {
context.read<CounterBloc>().add(const DecrementCounterEvent());
},
child: const Text('Decrement'),
),
const SizedBox(
height: 20,
),
ElevatedButton(
onPressed: () {
context.read<CounterBloc>().add(const ShowFailureEvent());
},
child: const Text('Trigger failure'),
),
const SizedBox(
height: 20,
),
ElevatedButton(
onPressed: () {
context.read<CounterBloc>().add(const PrintBlocHistoryEvent());
},
child: const Text('Print last 10 bloc state'),
),
BlocBuilder<CounterBloc, CounterState>(
builder: (context, state) {
return SizedBox(
height: 500,
child: ListView(
children: [
Text(
state.blocHistory,
style: Theme.of(context).textTheme.bodyMedium,
),
],
),
);
},
),
],
),
),
),
);
}
}
更多关于Flutter复用逻辑块插件reusable_bloc_base的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter复用逻辑块插件reusable_bloc_base的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,我可以为你提供一个关于如何在Flutter中使用reusable_bloc_base
插件的代码案例。这个插件旨在帮助开发者在Flutter应用中复用逻辑块(Bloc),从而提高代码的可维护性和复用性。
首先,确保你已经在pubspec.yaml
文件中添加了reusable_bloc_base
依赖:
dependencies:
flutter:
sdk: flutter
reusable_bloc_base: ^最新版本号 # 替换为实际可用的最新版本号
然后,运行flutter pub get
来安装依赖。
以下是一个简单的例子,展示了如何使用reusable_bloc_base
来创建一个可复用的Bloc,并在Flutter应用中使用它。
1. 创建一个可复用的Bloc
首先,我们定义一个Bloc来处理计数器的逻辑。这个Bloc将包含增加和减少计数的功能。
// counter_bloc.dart
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:reusable_bloc_base/reusable_bloc_base.dart';
part 'counter_event.dart';
part 'counter_state.dart';
class CounterBloc extends ReusableBloc<CounterEvent, CounterState> {
CounterBloc() : super(CounterState.initial()) {
on<IncrementEvent>((event, emit) => emit(state!.copy(count: state!.count + 1)));
on<DecrementEvent>((event, emit) => emit(state!.copy(count: state!.count - 1)));
}
@override
Stream<CounterState> mapEventToState(CounterEvent event) async* {
// 这个方法会被重写,但在这个例子中,我们已经在构造函数中处理了事件
yield* super.mapEventToState(event);
}
}
2. 定义事件和状态
接下来,我们定义事件和状态类。
// counter_event.dart
part of 'counter_bloc.dart';
abstract class CounterEvent {}
class IncrementEvent extends CounterEvent {}
class DecrementEvent extends CounterEvent {}
// counter_state.dart
part of 'counter_bloc.dart';
import 'package:equatable/equatable.dart';
class CounterState extends Equatable {
final int count;
const CounterState(this.count);
static const initial = CounterState(0);
@override
List<Object?> get props => [count];
CounterState copyWith(int? count) {
return CounterState(count ?? this.count);
}
}
3. 在UI中使用Bloc
最后,我们在Flutter的UI组件中使用这个Bloc。
// 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(
home: Scaffold(
appBar: AppBar(title: Text('Counter App')),
body: Center(
child: BlocProvider(
create: (context) => CounterBloc(),
child: CounterWidget(),
),
),
floatingActionButton: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
FloatingActionButton(
onPressed: () => context.read<CounterBloc>().add(IncrementEvent()),
tooltip: 'Increment',
child: Icon(Icons.add),
),
SizedBox(height: 10),
FloatingActionButton(
onPressed: () => context.read<CounterBloc>().add(DecrementEvent()),
tooltip: 'Decrement',
child: Icon(Icons.remove),
),
],
),
),
);
}
}
class CounterWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocBuilder<CounterBloc, CounterState>(
builder: (context, state) {
return Text('${state.count}');
},
);
}
}
在这个例子中,我们创建了一个CounterBloc
来处理计数器的状态管理,并在UI中使用BlocProvider
和BlocBuilder
来监听和显示状态的变化。CounterWidget
负责显示当前的计数,而两个FloatingActionButton
则用于触发增加和减少计数的事件。
通过这种方式,你可以利用reusable_bloc_base
插件来创建和管理可复用的Bloc逻辑,从而提高Flutter应用的代码质量和可维护性。