Flutter状态管理架构插件clean_bloc的使用
Flutter状态管理架构插件clean_bloc的使用
Clean Bloc 是一个围绕 bloc
包构建的封装器,它帮助实现清洁架构设计模式。
开始使用
安装
在你的 pubspec.yaml
文件中添加以下依赖:
dependencies:
clean_bloc: latest
使用
分页的 Clean Cubit
import 'package:clean_bloc/clean_bloc.dart';
import 'package:clean_network/clean_network.dart';
import 'package:injectable/injectable.dart';
@injectable
class UserCubit extends PaginatedCleanCubit<UserModel> {
final UserRepository _repository;
UserCubit(this._repository) {
init();
}
[@override](/user/override)
Pagination get initialPage =>
const Pagination.page(currentPage: 1, perPage: 6);
[@override](/user/override)
PaginatedEitherResponse<UserModel> Function(Pagination pagination)
get remoteCall {
return (pagination) {
final params = pagination as PagePagination;
return _repository.getUsers(
page: params.currentPage,
limit: params.perPage,
);
};
}
}
Clean Cubit
import 'package:clean_bloc/clean_bloc.dart';
import 'package:clean_network/clean_network.dart';
import 'package:injectable/injectable.dart';
@injectable
class UserCubit extends CleanCubit<UserModel> {
final UserRepository _repository;
UserCubit(this._repository) {
init();
}
[@override](/user/override)
EitherResponse<UserModel> Function() get remoteCall {
return () => _repository.getUser();
}
}
创建事件用于 Clean Bloc
import 'package:clean_bloc/clean_bloc.dart';
class UserAddEvent extends CleanEvent {
[@override](/user/override)
List<Object?> get props => [];
}
Clean Bloc
import 'package:clean_bloc/clean_bloc.dart';
import 'package:clean_network/clean_network.dart';
import 'package:injectable/injectable.dart';
@injectable
class UserBloc extends CleanBloc<UserModel> {
final UserRepository _repository;
UserBloc(this._repository) {
init();
on<UserAddEvent>(_handleAddEvent);
}
[@override](/user/override)
EitherResponse<UserModel> Function() get remoteCall {
return () => _repository.getUser();
}
/// 处理 [CleanEventInit] 事件
FutureOr<void> _handleAddEvent(
UserAddEvent event, Emitter<CleanState<T>> emit) async {
// 执行某些操作
}
}
创建事件用于分页的 Clean Bloc
import 'package:clean_bloc/clean_bloc.dart';
class UserAddEvent extends PaginatedCleanEvent {
[@override](/user/override)
List<Object?> get props => [];
}
分页的 Clean Bloc
import 'package:clean_bloc/clean_bloc.dart';
import 'package:clean_network/clean_network.dart';
import 'package:injectable/injectable.dart';
@injectable
class UserBloc extends PaginatedCleanBloc<UserModel> {
final UserRepository _repository;
UserBloc(this._repository) {
init();
on<UserAddEvent>(_handleAddEvent);
}
[@override](/user/override)
Pagination get initialPage =>
const Pagination.page(currentPage: 1, perPage: 6);
[@override](/user/override)
PaginatedEitherResponse<UserModel> Function(Pagination pagination)
get remoteCall {
return (pagination) {
final params = pagination as PagePagination;
return _repository.getUsers(
page: params.currentPage,
limit: params.perPage,
);
};
}
/// 处理 [UserAddEvent] 事件
FutureOr<void> _handleAddEvent(
UserAddEvent event,
Emitter<PaginatedCleanState<T>> emit,
) async {
// 执行某些操作
}
}
使用 Clean Bloc
import 'package:auto_route/auto_route.dart';
import 'package:clean_bloc/clean_bloc.dart';
import 'package:example/src/core/di/injector.dart';
import 'package:example/src/features/users/domain/models/user_model.dart';
import 'package:example/src/features/users/presentation/blocs/list/user_cubit.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
[@RoutePage](/user/RoutePage)()
class UsersPage extends StatelessWidget {
const UsersPage({super.key});
[@override](/user/override)
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => getIt<UserCubit>(),
child: Scaffold(
appBar: AppBar(
title: const Text('Users'),
),
body: const UserList(),
),
);
}
}
class UserList extends StatelessWidget {
const UserList({super.key});
[@override](/user/override)
Widget build(BuildContext context) {
return NotificationListener<ScrollNotification>(
onNotification: (notification) {
if (notification is ScrollEndNotification &&
notification.metrics.extentAfter == 0) {
context.read<UserCubit>().fetchMore();
return true;
}
return false;
},
child: PaginatedCleanBuilder<UserCubit, UserModel>(
successBuilder: (context, users, isLoadingMore) {
if (users.isEmpty) {
return const Center(
child: Text('No users found'),
);
}
return ListView.builder(
itemCount: isLoadingMore ? users.length + 1 : users.length,
itemBuilder: (context, index) {
if (index == users.length && isLoadingMore) {
return const Center(
child: CircularProgressIndicator(),
);
} else {
final user = users[index];
return ListTile(
title: Text(user.name),
subtitle: Text(user.email),
);
}
},
);
},
),
);
}
}
更多关于Flutter状态管理架构插件clean_bloc的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter状态管理架构插件clean_bloc的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
clean_bloc
是一个基于 Bloc
的状态管理架构插件,旨在帮助开发者更好地组织和维护 Flutter 应用的状态管理代码。它结合了 Clean Architecture 的思想,将业务逻辑与 UI 分离,使得代码更加模块化、可测试和可维护。
以下是如何使用 clean_bloc
插件的基本步骤和示例:
1. 安装 clean_bloc
插件
首先,你需要在 pubspec.yaml
文件中添加 clean_bloc
依赖:
dependencies:
flutter:
sdk: flutter
clean_bloc: ^0.1.0 # 请检查最新版本
然后运行 flutter pub get
来安装依赖。
2. 创建 Clean Architecture 层
Clean Architecture 通常分为以下几层:
- Presentation Layer: 负责 UI 和用户交互。
- Domain Layer: 包含业务逻辑和用例。
- Data Layer: 负责数据获取和存储。
在 clean_bloc
中,通常会将 Bloc
放在 Presentation Layer 中,而将业务逻辑放在 Domain Layer 中。
3. 创建 Bloc
在 clean_bloc
中,你可以使用 Bloc
或 Cubit
来管理状态。以下是一个简单的 Bloc
示例:
import 'package:clean_bloc/clean_bloc.dart';
// 定义事件
abstract class CounterEvent {}
class IncrementEvent extends CounterEvent {}
class DecrementEvent extends CounterEvent {}
// 定义状态
class CounterState {
final int count;
CounterState(this.count);
}
// 创建 Bloc
class CounterBloc extends Bloc<CounterEvent, CounterState> {
CounterBloc() : super(CounterState(0));
@override
Stream<CounterState> mapEventToState(CounterEvent event) async* {
if (event is IncrementEvent) {
yield CounterState(state.count + 1);
} else if (event is DecrementEvent) {
yield CounterState(state.count - 1);
}
}
}
4. 在 UI 中使用 Bloc
在 Flutter 的 UI 层,你可以使用 BlocBuilder
或 BlocProvider
来消费 Bloc
的状态。
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'counter_bloc.dart';
class CounterPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => CounterBloc(),
child: Scaffold(
appBar: AppBar(title: Text('Counter Example')),
body: BlocBuilder<CounterBloc, CounterState>(
builder: (context, state) {
return Center(
child: Text('Count: ${state.count}'),
);
},
),
floatingActionButton: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
FloatingActionButton(
onPressed: () => context.read<CounterBloc>().add(IncrementEvent()),
child: Icon(Icons.add),
),
SizedBox(height: 8),
FloatingActionButton(
onPressed: () => context.read<CounterBloc>().add(DecrementEvent()),
child: Icon(Icons.remove),
),
],
),
),
);
}
}
5. 测试 Bloc
clean_bloc
也支持单元测试。你可以使用 bloc_test
包来测试 Bloc
的行为。
import 'package:bloc_test/bloc_test.dart';
import 'package:test/test.dart';
import 'counter_bloc.dart';
void main() {
group('CounterBloc', () {
late CounterBloc counterBloc;
setUp(() {
counterBloc = CounterBloc();
});
blocTest<CounterBloc, CounterState>(
'emits [1] when IncrementEvent is added',
build: () => counterBloc,
act: (bloc) => bloc.add(IncrementEvent()),
expect: () => [CounterState(1)],
);
blocTest<CounterBloc, CounterState>(
'emits [-1] when DecrementEvent is added',
build: () => counterBloc,
act: (bloc) => bloc.add(DecrementEvent()),
expect: () => [CounterState(-1)],
);
});
}