Flutter异步状态管理插件async_cubits的使用
Flutter 异步状态管理插件 async_cubits 的使用
async_cubits
一个用于简化并一致地处理异步操作的插件包。
启发灵感
该插件包受到 Riverpod 的 FutureProvider
和 StreamProvider
的启发。AsyncValue
类与 riverpod
包中的类相似。请参阅 riverpod
包中的优秀工作。
安装 💻
要开始使用 Async Cubits,必须在您的机器上安装 Flutter SDK。
flutter pub add async_cubits
使用 🚀
导入包
import 'package:async_cubits/async_cubits.dart';
使用 FutureCubit
FutureCubits
是一种可以用于执行返回值的异步操作的 Cubit。例如,从 API 获取数据。
class GetUserCubit extends FutureCubit<User> {
final UserRepository _userRepository;
GetUserCubit(this._userRepository);
@override
Future<User> future() => _userRepository.getUser();
}
加载异步数据
要触发异步数据获取,使用 load()
方法。
当调用 load()
时,Cubit 将按以下顺序发出 AsyncValue<T>
:
AsyncValue.loading()
- 如果操作成功且数据可用,则
AsyncValue.data(fetchedData)
- 如果操作失败,则
AsyncValue.error(error, stackTrace)
在您的 UI 中,您可以使用 BlocProvider
和 BlocBuilder
来加载和访问数据。
BlocProvider(
create: (context) => GetUserCubit(
context.read<UserRepository>(),
)..load(), // 当创建 Cubit 时加载数据
child: BlocBuilder<GetUserCubit, AsyncState<User>>(
builder: (context, state) {
return state.when(
loading: () => CircularProgressIndicator(),
error: (error) => Text(error),
data: (user) => Text(user.name),
);
},
),
);
触发刷新
如果要触发数据的刷新,可以在 Cubit 上调用 refresh
方法。
ElevatedButton(
onPressed: () => context.read<GetUserCubit>().refresh(),
child: Text('Refresh'),
),
当调用 refresh()
时,Cubit 将按以下顺序发出 AsyncValue<T>
:
isLoading
为true
并且value
包含之前加载的值,这有助于显示之前加载的内容,然后立即切换到新值而不会显示加载指示器。如果您想显示加载指示器,可以在使用AsyncValue.when
时将skipLoadingOnRefresh
设置为false
- 如果操作成功并且有新值可用,则状态的
isLoading
变为false
并且value
包含新值 - 如果操作失败,则状态的
isLoading
变为false
,error
和stackTrace
不为空,并且value
包含之前加载的值。这种行为允许显示之前加载的内容,并带有刷新错误消息(要实现这一点,可以使用AsyncValue.when
方法中的skipError
)
因此,根据上述示例,如果数据成功获取,将渲染 Text(user.name)
并且在 Cubit 刷新时不会显示加载指示器。
使用新参数加载/刷新数据
要使用传递给 future
方法的新参数来加载/刷新数据,使用 FutureWithArgsCubit
。此 Cubit 的行为类似于 FutureCubit
。
class GetUserByIdCubit extends FutureWithArgsCubit<int, User> {
final UserRepository _userRepository;
GetUserCubit(this._userRepository);
@override
Future<User> future(int id) => _userRepository.getUserById(id);
}
然后使用参数调用 load
或 refresh
。
context.read<GetUserByIdCubit>().load(1);
或
context.read<GetUserByIdCubit>().refresh(1);
使用 StreamCubit
StreamCubits
是一种可以用于监听异步事件流的 Cubit。例如,监听来自 WebSocket 的数据流。
class NewMessageCubit extends StreamCubit<Message> {
final MessageRepository _messageRepository;
NewMessageCubit(this._messageRepository);
@override
Stream<Message> dataStream() => _messageRepository.newMessageStream();
}
StreamCubit
发出 AsyncValue<T>
,因此监听状态变化与 FutureCubit
类似。
class NewMessageWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
final cubit = context.watch<NewMessageCubit>();
final state = cubit.state;
return state.when(
loading: LoadingWidget.new,
error: (error, stackTrace) => ErrorWidget(error),
data: (data) => LoadedMessage(data),
);
}
}
使用 MutationCubit
MutationCubit
是一种专门设计用于处理异步突变的 Cubit。它促进了异步任务的执行,并在整个过程中管理各种状态,包括加载、成功和失败。通常用于突变后端、本地数据库等的状态。
示例:
class MyMutationCubit extends MutationCubit<String, int> {
@override
Future<int> mutation(String input) async {
// 在这里执行异步突变逻辑
// 例如,发起 API 调用、更新数据库等。
return 42; // 用实际结果替换
}
}
要调用突变,使用 invoke
方法:
cubit.invoke('input');
更多关于Flutter异步状态管理插件async_cubits的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter异步状态管理插件async_cubits的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何在Flutter应用中使用async_cubits
插件进行异步状态管理的代码示例。async_cubits
是一个简化和增强异步状态管理的库,它基于cubit
和bloc
架构。
首先,确保在你的pubspec.yaml
文件中添加async_cubits
依赖:
dependencies:
flutter:
sdk: flutter
async_cubits: ^最新版本号
然后运行flutter pub get
来获取依赖。
接下来,我们创建一个简单的示例,展示如何使用AsyncCubit
来管理异步数据。
1. 创建AsyncCubit
首先,创建一个AsyncCubit
类来处理数据获取逻辑。例如,我们创建一个用于获取用户数据的UserCubit
。
import 'package:async_cubits/async_cubits.dart';
import 'package:flutter/material.dart';
class UserState {
final bool isLoading;
final String? user;
final String? error;
UserState({
required this.isLoading,
this.user,
this.error,
});
UserState copyWith({
bool? isLoading,
String? user,
String? error,
}) {
return UserState(
isLoading: isLoading ?? this.isLoading,
user: user ?? this.user,
error: error ?? this.error,
);
}
}
class UserCubit extends AsyncCubit<UserState> {
UserCubit() : super(UserState(isLoading: false));
Future<void> fetchUser() async {
emit(state.copyWith(isLoading: true));
try {
// 模拟一个异步操作,例如从API获取用户数据
await Future.delayed(const Duration(seconds: 2));
final String user = 'John Doe';
emit(state.copyWith(isLoading: false, user: user));
} catch (e) {
emit(state.copyWith(isLoading: false, error: e.toString()));
}
}
}
2. 使用UserCubit在UI中
然后,在你的Flutter应用中使用这个UserCubit
来管理UI状态。
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:async_cubits_example/cubits/user_cubit.dart'; // 假设文件路径为cubits/user_cubit.dart
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Async Cubits Example')),
body: BlocProvider(
create: (_) => UserCubit(),
child: UserScreen(),
),
),
);
}
}
class UserScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocConsumer<UserCubit, UserState>(
listener: (context, state) {
// 这里可以处理一些需要响应状态变化的逻辑,比如显示SnackBar
},
builder: (context, state) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
if (state.isLoading)
CircularProgressIndicator(),
if (state.error != null)
Text('Error: ${state.error!}'),
if (state.user != null)
Text('User: ${state.user!}'),
ElevatedButton(
onPressed: () => context.read<UserCubit>().fetchUser(),
child: Text('Fetch User'),
),
],
),
);
},
);
}
}
3. 运行应用
运行你的Flutter应用,你应该会看到一个简单的界面,点击“Fetch User”按钮后,会显示一个加载指示器,然后显示获取到的用户数据或者错误信息。
这个示例展示了如何使用async_cubits
进行异步状态管理。通过AsyncCubit
,你可以轻松地管理UI的异步状态,同时保持代码的清晰和可维护性。