Flutter API管理插件api_bloc的使用

发布于 1周前 作者 itying888 来自 Flutter

Flutter API管理插件api_bloc的使用

标题

Flutter API管理插件api_bloc的使用

内容

图片 API Bloc Logo

版本信息 Pub Version Codecov

简介 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状态的泛型类,如loadingsuccesserror用于READ状态,以及idleloadingingsuccessfailederror用于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&lt;UserUpdateSuccessModel&gt;(
          data: UserUpdateSuccessModel.test()));
    } else {
      emit(const WriteFailedState&lt;UserUpdateFailedModel&gt;(
          data: UserUpdateFailedModel.test()));
    }
  }
}

ApiBloc(
  controller: UserUpdateController(),
  child: BlocConsumer&lt;UserUpdateController, WriteStates&gt;(
    listener: (context, state) {
      if (state is WriteSuccessState&lt;UserUpdateSuccessModel&gt;) {
      } else if (state is WriteFailedState&lt;UserUpdateFailedModel&gt;) {
      } 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&lt;ReadStates&gt; {
  ReadSentryController({
    this.autoRun = true,
    JSON args = const {},
  }) : super(value: const ReadLoadingState()) {
    if (autoRun) run(args);
  }

  @override
  Future&lt;void&gt; 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&lt;void&gt; onRequest(SentryHttpClient http, JSON args);

  Future&lt;void&gt; 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&lt;void&gt; onRequest(http, args) async {
    await Future.delayed(const Duration(milliseconds: 300));
    final response = await http.get(Uri('http://baseUrl/api/user/123'));
    emit(ReadSuccessState&lt;UserModel&gt;(data: UserModel.fromJSON(jsonDecode(response.body))));
  }
}

更多关于Flutter API管理插件api_bloc的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于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. 定义事件和状态

在上面的代码中,我们引用了UserEventUserState,现在我们来定义它们:

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中使用BlocProviderBlocBuilder来连接你的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来连接和管理状态。希望这对你有所帮助!

回到顶部