Flutter网络请求拦截插件api_service_interceptor的使用

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

Flutter网络请求拦截插件api_service_interceptor的使用

API Service Interceptor

pub package popularity likes pub points GH Actions style: effective dart Awesome Flutter

Api Service interceptor 是一个 Flutter 包,它可以帮助你以最简单的方式从服务器获取和传递数据。

安装

在你的 pubspec.yaml 文件中添加依赖:

dependencies:
  api_service_interceptor: latest

或者直接使用命令行工具:

flutter pub add api_service_interceptor

功能

ApiServiceInterceptor 类有两个主要方法:

  • requestToServer()
  • multipartRequestToServer()

requestToServer()

此方法用于发送普通请求到服务器。它接受四个参数:

参数 描述
String requestUrl (必填) API 的 URL
ApiRequestMethod requestMethod (必填) 请求方法,例如 POST、GET 等
Object? bodyParams (可选) 请求体,可以是字符串、列表或映射
Map<String, String>? headers (可选) 请求头,包含关于资源或客户端的信息

示例代码:

ApiResponseModel responseModel = await apiServiceInterceptor.requestToServer(
  requestUrl: "https://example.com/api/login",
  requestMethod: ApiRequestMethod.postRequest,
  bodyParams: jsonEncode({
    "username": "user",
    "password": "pass"
  }),
  headers: {'Content-Type': 'application/json'}
);

multipartRequestToServer()

此方法用于发送多部分表单数据(如文件上传)。它接受七个参数:

参数 描述
String requestUrl (必填) API 的 URL
String requestMethod (必填) 请求方法,例如 POST、GET 等
Map<String, String> headers (必填) 请求头,包含关于资源或客户端的信息
String multipartFileField (必填) 文件字段名
String multipartFileValue (必填) 文件路径或内容
String? multipartFileName (可选) 文件名
MediaType? multipartContentType (可选) 文件类型,默认为 application/octet-stream

示例代码:

ApiResponseModel responseModel = await apiServiceInterceptor.multipartRequestToServer(
  requestUrl: "https://example.com/api/upload",
  requestMethod: "POST",
  headers: {'Content-Type': 'multipart/form-data'},
  multipartFileField: "file",
  multipartFileValue: "/path/to/file.txt",
  multipartFileName: "file.txt",
  multipartContentType: MediaType("text", "plain")
);

响应模型

ApiResponseModel 类用于存储服务器响应的数据,包含两个字段:

  • _statusCode: 存储状态码,类型为 int
  • _responseJson: 存储响应内容,类型为 String

枚举

ApiRequestMethod 枚举定义了所有可能的 HTTP 请求方法,例如:

enum ApiRequestMethod {
  get,
  post,
  put,
  delete,
  patch,
  head,
  options,
  postRequest, // 自定义名称
}

使用示例

以下是一个完整的登录页面示例,展示了如何使用 api_service_interceptor 进行用户登录:

import 'dart:convert';
import 'package:api_service_interceptor/api_service_interceptor.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:shared_preferences/shared_preferences.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await initDependency();
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      debugShowCheckedModeBanner: false,
      initialBinding: LoginBinding(),
      home: const LoginScreen(),
    );
  }
}

class LoginScreen extends StatefulWidget {
  const LoginScreen({super.key});

  @override
  State<LoginScreen> createState() => _LoginScreenState();
}

class _LoginScreenState extends State<LoginScreen> {
  final formKey = GlobalKey<FormState>();
  final TextEditingController emailController = TextEditingController();
  final TextEditingController passwordController = TextEditingController();
  bool showPassword = false;
  bool isSubmit = false;

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        body: SingleChildScrollView(
          padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 100),
          child: Form(
            key: formKey,
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                const Text('Login', style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold)),
                const SizedBox(height: 20),
                TextFormField(
                  controller: emailController,
                  validator: (value) => value?.isEmpty ?? true ? "Please enter a username" : null,
                  decoration: const InputDecoration(hintText: 'Enter your username'),
                ),
                const SizedBox(height: 20),
                TextFormField(
                  controller: passwordController,
                  obscureText: !showPassword,
                  validator: (value) => value?.isEmpty ?? true ? "Password Field Not Be Empty" : null,
                  decoration: InputDecoration(
                    hintText: 'Enter your password',
                    suffixIcon: IconButton(
                      icon: Icon(showPassword ? Icons.visibility_off : Icons.visibility),
                      onPressed: () => setState(() => showPassword = !showPassword),
                    ),
                  ),
                ),
                const SizedBox(height: 30),
                ElevatedButton(
                  onPressed: () async {
                    if (formKey.currentState!.validate()) {
                      setState(() => isSubmit = true);
                      ApiResponseModel responseModel = await loginRepo.loginUser(
                        username: emailController.text.trim(),
                        password: passwordController.text.trim(),
                      );

                      if (responseModel.statusCode == 200) {
                        final loginResponseModel = LoginResponseModel.fromJson(jsonDecode(responseModel.responseJson));
                        await loginRepo.apiServiceInterceptor.sharedPreferences.setString("accessTokenKey", loginResponseModel.token ?? "");
                        print("Login Successfully");
                      } else {
                        print("Login Failed with status code ${responseModel.statusCode}");
                      }
                      setState(() => isSubmit = false);
                    }
                  },
                  child: isSubmit ? const CircularProgressIndicator(color: Colors.white) : const Text("Continue"),
                )
              ],
            ),
          ),
        ),
      ),
    );
  }
}

class LoginBinding extends Bindings {
  @override
  void dependencies() {
    Get.lazyPut(() => LoginRepo(apiServiceInterceptor: Get.find()));
    Get.lazyPut(() => LoginController(loginRepo: Get.find()));
  }
}

class LoginController extends GetxController {
  final LoginRepo loginRepo;

  LoginController({required this.loginRepo});

  Future<void> signInUser(String username, String password) async {
    ApiResponseModel responseModel = await loginRepo.loginUser(username: username, password: password);

    if (responseModel.statusCode == 200) {
      final loginResponseModel = LoginResponseModel.fromJson(jsonDecode(responseModel.responseJson));
      await loginRepo.apiServiceInterceptor.sharedPreferences.setString("accessTokenKey", loginResponseModel.token ?? "");
      print("Login Successfully");
    } else {
      print("Login Failed with status code ${responseModel.statusCode}");
    }
  }
}

class LoginRepo {
  final ApiServiceInterceptor apiServiceInterceptor;

  LoginRepo({required this.apiServiceInterceptor});

  Future<ApiResponseModel> loginUser({required String username, required String password}) async {
    String url = "https://example.com/api/login";

    Map<String, String> bodyParams = {
      "username": username,
      "password": password
    };

    Map<String, String> headers = {'Content-Type': 'application/json'};

    ApiResponseModel responseModel = await apiServiceInterceptor.requestToServer(
      requestUrl: url,
      requestMethod: ApiRequestMethod.postRequest,
      bodyParams: jsonEncode(bodyParams),
      headers: headers
    );

    return responseModel;
  }
}

class LoginResponseModel {
  String? token;

  LoginResponseModel({this.token});

  factory LoginResponseModel.fromJson(Map<String, dynamic> json) {
    return LoginResponseModel(token: json['token']);
  }

  Map<String, dynamic> toJson() {
    return {'token': token};
  }
}

Future<void> initDependency() async {
  final sharedPreference = await SharedPreferences.getInstance();
  Get.lazyPut(() => sharedPreference, fenix: true);
  Get.lazyPut(() => ApiServiceInterceptor(sharedPreferences: Get.find()), fenix: true);
}

这个示例展示了如何使用 api_service_interceptor 包进行用户登录,并处理响应数据。你可以根据需要修改和扩展此代码。


更多关于Flutter网络请求拦截插件api_service_interceptor的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter网络请求拦截插件api_service_interceptor的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter项目中使用api_service_interceptor插件来进行网络请求拦截的示例代码。api_service_interceptor允许你在发送请求和接收响应时执行一些自定义逻辑,例如添加认证令牌、记录日志或处理错误。

首先,确保你已经在pubspec.yaml文件中添加了api_service_interceptor依赖:

dependencies:
  flutter:
    sdk: flutter
  dio: ^4.0.0  # 假设你使用的是dio作为HTTP客户端
  api_service_interceptor: ^x.y.z  # 请替换为最新版本号

然后,运行flutter pub get来安装依赖。

接下来,我们需要在Flutter项目中配置并使用这个拦截器。以下是一个完整的示例:

  1. 创建拦截器
import 'package:dio/dio.dart';
import 'package:api_service_interceptor/api_service_interceptor.dart';

class AuthInterceptor extends ApiServiceInterceptor {
  @override
  Future<void> onRequest(RequestOptions options, ApiServiceInterceptorHandler handler) async {
    // 在这里你可以添加认证令牌到请求头
    options.headers['Authorization'] = 'Bearer YOUR_ACCESS_TOKEN';
    // 调用handler.next()继续请求流程
    handler.next(options);
  }

  @override
  Future<void> onResponse(Response<dynamic> response, ApiServiceInterceptorHandler handler) async {
    // 在这里你可以处理响应数据,比如打印日志
    print('Response: ${response.data}');
    // 调用handler.next()继续响应流程
    handler.next(response);
  }

  @override
  Future<void> onError(DioError err, ApiServiceInterceptorHandler handler) async {
    // 在这里你可以处理错误,比如记录错误日志或显示错误消息
    print('Error: ${err.message}');
    // 调用handler.next()继续错误处理流程(如果需要)
    handler.next(err);
  }
}
  1. 配置Dio实例
import 'package:dio/dio.dart';
import 'path/to/your/auth_interceptor.dart'; // 替换为实际的路径

class ApiService {
  late Dio dio;

  ApiService() {
    dio = Dio(
      BaseOptions(
        baseUrl: 'https://your.api.base.url/',
        connectTimeout: 5000,
        receiveTimeout: 3000,
      ),
    );

    // 添加拦截器
    dio.interceptors.add(AuthInterceptor());
  }

  // 示例请求方法
  Future<dynamic> fetchData() async {
    try {
      Response<dynamic> response = await dio.get('/endpoint');
      return response.data;
    } catch (e) {
      throw e;
    }
  }
}
  1. 使用ApiService
import 'package:flutter/material.dart';
import 'path/to/your/api_service.dart'; // 替换为实际的路径

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  late ApiService apiService;

  MyApp() {
    apiService = ApiService();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Flutter Network Interception Example'),
        ),
        body: Center(
          child: FutureBuilder<dynamic>(
            future: apiService.fetchData(),
            builder: (context, snapshot) {
              if (snapshot.connectionState == ConnectionState.done) {
                if (snapshot.hasError) {
                  return Text('Error: ${snapshot.error}');
                } else {
                  return Text('Data: ${snapshot.data}');
                }
              } else {
                return CircularProgressIndicator();
              }
            },
          ),
        ),
      ),
    );
  }
}

这个示例展示了如何使用api_service_interceptor插件来拦截网络请求和响应。你可以根据需要在拦截器中添加更多的逻辑,比如动态获取认证令牌、处理特定的HTTP状态码等。希望这个示例能帮助你更好地理解和使用api_service_interceptor插件。

回到顶部