Flutter状态管理与工具集插件flutter_bloc_toolbox的使用
Flutter状态管理与工具集插件flutter_bloc_toolbox的使用
flutter_bloc_toolbox
是基于优秀的 flutter_bloc package 构建的,包含了一些有用的blocs/cubits。以下是其主要特性和示例代码。
Features
BoolCubit
这是一个简单的布尔cubit,用于管理布尔状态,适用于复选框或其他选项/退出选择。
/// 创建时带有初始值
final BoolCubit myBoolCubit = BoolCubit(initialValue: true);
/// 用于发出新的布尔状态
myBoolCubit.changeValue(false);
/// 发出 !value 状态
myBoolCubit.toggleValue();
FetchAndRefresh
这个cubit用于管理一个值的获取和刷新。可以与 FetchAndRefreshStateValidWrapper
一起使用以实现自动加载和错误显示。
typedef FetchAndRefreshStateTest = FetchAndRefreshState<String, PersonEntity>;
typedef FetchAndRefreshCubitTest = FetchAndRefreshCubit<FetchAndRefreshStateTest, String, PersonEntity>;
getObjectTest({required String idToGet}) => personRepository.getObject(idToGet);
FetchAndRefreshCubit fetchAndRefreshCubit = FetchAndRefreshCubitTest(
fetchObject: getObjectTest,
);
/// 获取值
fetchAndRefreshCubit.fetch(idToFetch: 'ID');
/// 刷新值
fetchAndRefreshCubit.refresh();
/// 重置cubit
fetchAndRefreshCubit.reset();
...
FetchAndRefreshStateValidWrapper<
FetchAndRefreshCubitTest,
FetchAndRefreshStateTest,
FetchAndRefreshWithValueState<String, PersonEntity>,
String,
PersonEntity>(
cubit: fetchAndRefreshCubit,
idToCheck: 'ID',
validRender: (BuildContext context, FetchAndRefreshWithValueState<String, PersonEntity> localState) {
return ...;
},
);
FetchAndRefreshPaginated
这个cubit用于管理分页值的获取和刷新,允许加载更多项。
typedef FetchAndRefreshPaginatedStateTest = FetchAndRefreshPaginatedState<String, PaginationEntity<PersonEntity>>;
typedef FetchAndRefreshPaginatedCubitTest = FetchAndRefreshPaginatedCubit<FetchAndRefreshPaginatedStateTest, String, PaginationEntity<PersonEntity>>;
getObjectTest({
required String idToGet,
bool loadMore = false,
bool getAll = false,
FetchAndRefreshPaginatedState? currentState,
}) async {
PaginationEntity<PersonEntity>? personsPaginationEntity;
if (loadMore && currentState is FetchAndRefreshPaginatedWithValueState) {
personsPaginationEntity = currentState.object;
}
PaginationEntity<PersonEntity>? persons = personsPaginationEntity != null
? await personRepository.getPaginationObject(
idToGet,
onlyOnePage: !getAll,
currentPaginationEntity: personsPaginationEntity,
)
: await personRepository.getPaginationObject(
idToGet,
onlyOnePage: !getAll,
);
return persons;
}
FetchAndRefreshPaginatedCubit fetchAndRefreshPaginatedCubit = FetchAndRefreshPaginatedCubitTest(
fetchObject: getObjectTest,
);
/// 获取值
fetchAndRefreshPaginatedCubit.fetch(idToFetch: 'ID');
/// 加载更多
fetchAndRefreshPaginatedCubit.fetch(idToFetch: 'ID', loadMore: true);
FilterEnumCubit
这个cubit用于管理过滤器列表的选择情况。
typedef FilterEnumTest = FilterEnumEntity<MockEnum>;
typedef FilterState = FilterEnumState<MockEnum, FilterEnumTest>;
typedef FilterCubit = FilterEnumCubit<MockEnum, FilterEnumTest, FilterState>;
FilterCubit filterCubit = FilterCubit(
FilterEnumInitialState<MockEnum, FilterEnumTest>(
MockEnum.values,
(MockEnum s, bool b) => FilterEnumTest(s, b),
),
enumValues: MockEnum.values,
enumBuilder: (MockEnum s, bool b) => FilterEnumEntity(s, b),
selectedByDefault: selectedByDefault,
);
/// 更改过滤器选择
filterCubit.toggleEnum(MockEnum.mock1);
filterCubit.toggleEnum(MockEnum.mock2);
filterCubit.toggleEnum(MockEnum.mock1);
/// 重置为默认值
filterCubit.setDefaultFilters();
/// 从列表设置
filterCubit.setFiltersFromList(const [FilterEnumEntity(MockEnum.mock3, true)]);
filterCubit.setFilterFromPicked(const [MockEnum.mock3, MockEnum.mock1, MockEnum.mock2]);
SearchTextCubit
这个cubit用于管理文本搜索。
SearchTextCubit searchTextCubit = SearchTextCubit();
/// 更改文本
searchTextCubit.setText(textToSearch);
/// 清空文本
searchTextCubit.eraseText();
SortEnumCubit
这个cubit用于管理排序。
List<SortEnumTest> availableSorts = const [
SortEnumTest(
ascendant: true,
sortEnum: MockEnum.mock1,
),
SortEnumTest(
ascendant: false,
sortEnum: MockEnum.mock1,
),
SortEnumTest(
ascendant: true,
sortEnum: MockEnum.mock2,
),
SortEnumTest(
ascendant: false,
sortEnum: MockEnum.mock3,
),
SortEnumTest(
ascendant: true,
sortEnum: MockEnum.mock4,
),
SortEnumTest(
ascendant: false,
sortEnum: MockEnum.mock4,
),
];
int defaultIndex = 2;
SortCubit sortCubit = SortCubit(
SortEnumInitialState(
sortEntity: availableSorts.elementAt(defaultIndex),
),
availableSorts: availableSorts,
defaultIndex: defaultIndex,
);
/// 更改排序
sortCubit.changeSort(availableSorts.first);
示例Demo
下面是一个完整的Flutter应用示例,展示了如何使用PersonsFetchAndRefreshPaginatedCubit
来获取和显示分页数据,并提供加载更多按钮。
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:example/data/person_repository.dart';
import 'package:example/logic/fetch_and_refresh_paginated/persons_fetch_and_refresh_paginated_cubit.dart';
import 'package:example/presentation/persons_fetch_and_refresh_state_valid_wrapper.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final String idToFetch = 'idToFetch';
final PersonsFetchAndRefreshPaginatedCubit paginatedCubit = PersonsFetchAndRefreshPaginatedCubit(
PersonRepository(),
);
@override
void initState() {
super.initState();
paginatedCubit.fetch(idToFetch: idToFetch);
}
@override
void dispose() {
paginatedCubit.close();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: const Text('Example'),
),
body: Center(
child: CustomScrollView(
slivers: [
BlocBuilder<PersonsFetchAndRefreshPaginatedCubit, FetchAndRefreshPaginatedState<String, PaginationEntity<PersonEntity>>>(
bloc: paginatedCubit,
builder: (context, state) {
if (state is FetchAndRefreshPaginatedWithValueState) {
return SliverList.builder(
itemCount: state.persons.data.length,
itemBuilder: (BuildContext context, int i) => Container(
margin: const EdgeInsets.all(20),
child: Text(
'${state.persons.data.elementAt(i).firstName} ${state.persons.data.elementAt(i).lastName}'),
),
);
} else {
return const SliverToBoxAdapter(child: Center(child: CircularProgressIndicator()));
}
},
),
BlocBuilder<PersonsFetchAndRefreshPaginatedCubit, FetchAndRefreshPaginatedState<String, PaginationEntity<PersonEntity>>>(
bloc: paginatedCubit,
builder: (context, state) {
return SliverToBoxAdapter(
child: TextButton(
onPressed: () => paginatedCubit.fetch(
idToFetch: idToFetch,
loadMore: true,
),
child: const Text('More'),
),
);
},
),
],
),
),
);
}
}
在这个示例中,我们创建了一个简单的Flutter应用程序,它使用 PersonsFetchAndRefreshPaginatedCubit
来获取和显示分页数据,并提供了一个“更多”按钮来加载更多数据。通过这种方式,您可以更好地理解和使用 flutter_bloc_toolbox
插件中的功能。
更多关于Flutter状态管理与工具集插件flutter_bloc_toolbox的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter状态管理与工具集插件flutter_bloc_toolbox的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,关于Flutter中的状态管理与工具集插件flutter_bloc_toolbox
的使用,以下是一个具体的代码案例来展示如何结合Flutter的Bloc状态管理与flutter_bloc_toolbox
插件进行开发。
环境设置
首先,确保你的Flutter项目已经配置好flutter_bloc
和flutter_bloc_toolbox
。在你的pubspec.yaml
文件中添加以下依赖:
dependencies:
flutter:
sdk: flutter
flutter_bloc: ^8.0.0 # 请检查最新版本
flutter_bloc_toolbox: ^0.3.0 # 请检查最新版本
然后运行flutter pub get
来安装依赖。
创建一个简单的计数器应用
1. 定义事件、状态和Bloc
首先,我们定义一个简单的事件(IncrementEvent)和状态(CounterState),然后创建一个Bloc来处理这些事件并更新状态。
// counter_event.dart
import 'package:equatable/equatable.dart';
abstract class CounterEvent extends Equatable {
const CounterEvent();
}
class IncrementEvent extends CounterEvent {
@override
List<Object> get props => [];
}
// counter_state.dart
import 'package:equatable/equatable.dart';
class CounterState extends Equatable {
final int count;
const CounterState({required this.count});
@override
List<Object> get props => [count];
}
// counter_bloc.dart
import 'package:bloc/bloc.dart';
import 'package:flutter_bloc_toolbox/flutter_bloc_toolbox.dart';
import 'counter_event.dart';
import 'counter_state.dart';
class CounterBloc extends Bloc<CounterEvent, CounterState> with BlocLogger {
CounterBloc() : super(CounterState(count: 0)) {
on<IncrementEvent>((event, emit) {
emit(state.copyWith(count: state.count + 1));
});
}
}
2. 使用flutter_bloc_toolbox中的BlocProvider
在main.dart
文件中,使用flutter_bloc_toolbox
提供的BlocProvider
来提供我们的CounterBloc
。
// main.dart
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_bloc_toolbox/flutter_bloc_toolbox.dart';
import 'counter_bloc.dart';
import 'counter_page.dart';
void main() {
runApp(
BlocProvider<CounterBloc>(
create: (_) => CounterBloc(),
child: MyApp(),
),
);
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: CounterPage(),
);
}
}
3. 创建UI组件
在counter_page.dart
文件中,创建一个简单的界面来显示计数器的值,并提供一个按钮来增加计数。
// counter_page.dart
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'counter_bloc.dart';
import 'counter_event.dart';
class CounterPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Counter App')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'${context.bloc<CounterBloc>().state.count}',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
context.read<CounterBloc>().add(IncrementEvent());
},
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
运行应用
现在,你可以运行你的Flutter应用,应该能看到一个简单的计数器应用,点击浮动按钮会增加计数器的值。
这个示例展示了如何使用flutter_bloc
进行状态管理,并结合flutter_bloc_toolbox
提供的BlocProvider
来提供Bloc实例。flutter_bloc_toolbox
还包括其他有用的功能,比如日志记录(在这里我们通过with BlocLogger
使用了它),你可以根据需要进一步探索和使用这些功能。