Flutter API管理插件api_bloc的使用
Flutter API管理插件api_bloc的使用
标题
Flutter API管理插件api_bloc的使用
内容
图片
简介 Flutter widgets designed to simplify the implementation of the BLoC pattern for REST APIs within an MVC architecture. Significantly reduces boilerplate code by automating BLoC pattern and test generation for handling REST API interactions.
功能
- 显著减少与REST API交互的BLoC模式的代码冗余。
- 处理各种API状态的泛型类,如
loading
、success
和error
用于READ
状态,以及idle
、loadinging
、success
、failed
和error
用于WRITE
状态。 - 自定义构建器和监听函数以响应状态变化。
- 通过命令生成API bloc模式和测试。
开始使用
要在项目中使用此库,请在pubspec.yaml
文件中添加api_bloc
作为依赖项。
dependencies:
api_bloc: ^3.0.1
并运行以下命令激活api_bloc_cli
:
dart pub global activate api_bloc
获取数据示例(Fetch Scenario)
import 'package:api_bloc/api_bloc.dart';
class GetUserController extends ReadController {
@override
Future<void> onRequest(Map<String, dynamic> args) async {
// 模拟延迟
await Future.delayed(const Duration(seconds: 1));
Response response = await Dio().get(
'https://reqres.in/api/users/2',
onReceiveProgress: (received, total) {
emit(ReadLoadingState<double>(data: received / total));
},
);
emit(ReadSuccessState<UserDetailModel>(
data: UserDetailModel.fromJSON(response.data)));
}
}
ApiBloc(
controller: GetUserController(),
child: BlocBuilder<GetUserController, ReadStates>(
builder: (context, state, child) {
if (state is ReadSuccessState<UserDetailModel>) {
} else if (state is ReadErrorState) {}
return Text(state.message);
},
),
);
当控制器首次初始化时,ReadController
会自动运行请求函数。 如果需要重新运行它,可以调用controller.run()
。
提交数据示例(Submitting Scenario)
import 'package:api_bloc/api_bloc.dart';
class UserUpdateController extends WriteController {
@override
Future<void> onRequest(Map<String, dynamic> args) async {
// 延迟以使加载状态更明显。
await Future.delayed(const Duration(milliseconds: 300));
// 发送成功或失败状态
if (isSuccess {
emit(const WriteSuccessState<UserUpdateSuccessModel>(
data: UserUpdateSuccessModel.test()));
} else {
emit(const WriteFailedState<UserUpdateFailedModel>(
data: UserUpdateFailedModel.test()));
}
}
}
ApiBloc(
controller: UserUpdateController(),
child: BlocConsumer<UserUpdateController, WriteStates>(
listener: (context, state) {
if (state is WriteSuccessState<UserUpdateSuccessModel>) {
} else if (state is WriteFailedState<UserUpdateFailedModel>) {
} else if (state is WriteErrorState) {}
},
builder: (context, state, child) {
if (state is WriteLoadingState) {}
return Text(state.message);
},
),
);
WriteControllerRequest 的的初始状态为 idle
状态,因此要运行请求需要手动触发 controller.run()
。
生成API bloc结构(Optional)
要快速创建一个模块,例如 GET
细节和 GET
列表,以及 PUT
更新、POST
创建和 DELETE
删除模块名为 USER
使用此库,运行以下命令:
dart run api_bloc --output lib/src --create user --read detail,list --write update,create,delete
这将在您的项目中生成以下结构:
📂 lib/src/user/
📄 lib/src/user/user.dart
📄 lib/src/user/controllers/user_detail.dart
📄 lib/src/user/controllers/user_list.dart
📄 lib/src/user/controllers/user_update.dart
📄 lib/src/user/controllers/user_create.dart
📄 lib/src/user/controllers/user_delete.dart
📄 lib/src/user/models/user_detail.dart
📄 lib/src/user/models/user_list.dart
📄 lib/src/user/models/user_update.dart
📄 lib/src/user/models/user_create.dart
📄 lib/src/user/models/user_delete.dart
📄 lib/src/user/views/user_detail.dart
📄 lib/src/user/views/user_list.dart
📄 lib/src/user/views/user_update.dart
📄 lib/src/user/views/user_create.dart
📄 lib/src/user/views/user_delete.dart
📂 test/src/user/
📄 test/src/user/controllers/user_detail.dart
📄 test/src/user/controllers/user_list.dart
📄 test/src/user/controllers/user_update.dart
📄 test/src/user/controllers/user_create.dart
📄 test/src/user/controllers/user_delete.dart
📄 test/src/user/models/user_detail.dart
📄 test/src/user/models/user_list.dart
📄 test/src/user/models/user_update.dart
📄 test/src/user/models/user_create.dart
📄 test/src/user/models/user_delete.dart
📄 test/src/user/views/user_detail.dart
📄 test/src/user/views/user_list.dart
📄 test/src/user/views/user_update.dart
📄 test/src/user/views/user_create.dart
📄 test/src/user/views/user_delete.dart
Sentry集成 您也可以通过创建自定义控制器来将此库与Sentry集成,如下所示:
abstract class ReadSentryController extends BlocRequest<ReadStates> {
ReadSentryController({
this.autoRun = true,
JSON args = const {},
}) : super(value: const ReadLoadingState()) {
if (autoRun) run(args);
}
@override
Future<void> run([JSON args = const {}]) async {
emit(const ReadLoadingState());
final http = SentryHttpClient();
try {
await onRequest(http, args);
} catch (e, s) {
await onError(e, s);
} finally {
http.close();
}
}
Future<void> onRequest(SentryHttpClient http, JSON args);
Future<void> onError(dynamic e, StackTrace s) async {
await Sentry.captureException(e, stackTrace: s);
emit(ReadErrorState(message: e.toString(), data: s));
}
final bool autoRun;
}
每当需要与API进行交互时,创建一个类似这样的控制器:
class ReadUserRequest extends ReadSentryController {
Future<void> onRequest(http, args) async {
await Future.delayed(const Duration(milliseconds: 300));
final response = await http.get(Uri('http://baseUrl/api/user/123'));
emit(ReadSuccessState<UserModel>(data: UserModel.fromJSON(jsonDecode(response.body))));
}
}
更多关于Flutter API管理插件api_bloc的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter API管理插件api_bloc的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,关于在Flutter项目中使用api_bloc
插件进行API管理,这里提供一个简要的代码示例来展示其基本用法。api_bloc
是一个状态管理库,特别适用于处理与API交互相关的逻辑。
首先,确保你已经在pubspec.yaml
文件中添加了api_bloc
依赖:
dependencies:
flutter:
sdk: flutter
api_bloc: ^最新版本号 # 请替换为实际的最新版本号
然后运行flutter pub get
来安装依赖。
1. 定义API服务
首先,我们需要定义一个API服务类,用于执行实际的网络请求。例如,我们可以创建一个简单的用户服务类:
import 'package:dio/dio.dart';
import 'package:api_bloc/api_bloc.dart';
class UserService {
final Dio dio;
UserService({required this.dio});
Future<User> fetchUser(int userId) async {
final response = await dio.get('https://jsonplaceholder.typicode.com/users/$userId');
return User.fromJson(response.data);
}
}
class User {
int id;
String name;
String email;
User({required this.id, required this.name, required this.email});
factory User.fromJson(Map<String, dynamic> json) {
return User(
id: json['id'],
name: json['name'],
email: json['email'],
);
}
}
2. 创建API Repository
接下来,我们创建一个API Repository,它将使用我们的UserService来执行API调用,并将结果封装为Bloc事件和状态。
import 'package:api_bloc/api_bloc.dart';
import 'package:equatable/equatable.dart';
import 'user_service.dart';
part 'user_event.dart';
part 'user_state.dart';
class UserRepository extends ApiRepository<UserEvent, UserState> {
final UserService userService;
UserRepository({required this.userService}) : super(initialState: UserState.initial());
@override
Stream<UserState> mapEventToState(UserEvent event) async* {
if (event is FetchUserRequest) {
yield UserState.loading();
try {
final user = await userService.fetchUser(event.userId);
yield UserState.loaded(user: user);
} catch (_) {
yield UserState.error();
}
}
}
}
3. 定义事件和状态
在上面的代码中,我们引用了UserEvent
和UserState
,现在我们来定义它们:
user_event.dart
part of 'user_repository.dart';
abstract class UserEvent extends Equatable {
const UserEvent();
@override
List<Object?> get props => [];
}
class FetchUserRequest extends UserEvent {
final int userId;
const FetchUserRequest({required this.userId});
@override
List<Object?> get props => [userId];
}
user_state.dart
part of 'user_repository.dart';
abstract class UserState extends Equatable {
const UserState();
@override
List<Object?> get props => [];
}
class UserStateInitial extends UserState {
const UserStateInitial();
}
class UserStateLoading extends UserState {
const UserStateLoading();
}
class UserStateLoaded extends UserState {
final User user;
const UserStateLoaded({required this.user});
@override
List<Object?> get props => [user];
}
class UserStateError extends UserState {
const UserStateError();
}
4. 使用BlocProvider和BlocBuilder
最后,在你的Flutter UI中使用BlocProvider
和BlocBuilder
来连接你的Bloc和UI。
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'user_repository.dart';
void main() {
final userRepository = UserRepository(userService: UserService(dio: Dio()));
runApp(
BlocProvider<UserRepository>(
create: (context) => userRepository,
child: MyApp(),
),
);
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: UserScreen(),
);
}
}
class UserScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('User Info')),
body: Center(
child: BlocBuilder<UserRepository, UserState>(
builder: (context, state) {
if (state is UserStateLoading) {
return CircularProgressIndicator();
} else if (state is UserStateLoaded) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('Name: ${state.user.name}'),
Text('Email: ${state.user.email}'),
],
);
} else if (state is UserStateError) {
return Text('Failed to load user');
} else {
return ElevatedButton(
onPressed: () {
context.read<UserRepository>().add(FetchUserRequest(userId: 1));
},
child: Text('Fetch User'),
);
}
},
),
),
);
}
}
这个示例展示了如何使用api_bloc
进行API管理,包括定义服务、创建Repository、定义事件和状态,以及在UI中使用BlocProvider和BlocBuilder来连接和管理状态。希望这对你有所帮助!