MST

星途 面试题库

面试题:Flutter Dio插件拦截器的复杂配置与应用

假设你正在开发一个需要处理多种不同API请求的Flutter应用,这些请求可能来自不同的服务器,且每个服务器有不同的认证机制。请描述如何使用Dio插件的拦截器来统一管理这些请求的认证头信息,并且当认证信息过期时,能够自动刷新并重新发起原请求,同时要考虑到多个请求并发时的情况。
44.2万 热度难度
前端开发Flutter

知识考点

AI 面试

面试题答案

一键面试
  1. 安装Dio插件: 在pubspec.yaml文件中添加dio依赖:
    dependencies:
      dio: ^[latest_version]
    
    然后运行flutter pub get
  2. 创建认证拦截器: 首先定义一个认证拦截器类,它继承自InterceptorsWrapper
    class AuthInterceptor extends InterceptorsWrapper {
      // 存储认证信息,如token
      String? token;
      // 标记是否正在刷新token
      bool isRefreshing = false;
      // 用于等待刷新token完成的队列
      final List<RequestOptions> requestQueue = [];
    
      @override
      void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
        if (token!= null) {
          options.headers['Authorization'] = 'Bearer $token';
        }
        handler.next(options);
      }
    
      @override
      void onResponse(Response response, ResponseInterceptorHandler handler) {
        // 如果认证未过期,直接返回响应
        if (response.statusCode == 200) {
          handler.next(response);
        } else {
          // 处理认证过期等其他错误情况
          handleError(response, handler);
        }
      }
    
      @override
      void onError(DioError err, ErrorInterceptorHandler handler) {
        if (err.response?.statusCode == 401) {
          // 认证过期,处理认证过期逻辑
          handleError(err.response, handler);
        } else {
          handler.next(err);
        }
      }
    
      void handleError(Response? response, [ErrorInterceptorHandler? handler]) {
        if (!isRefreshing) {
          isRefreshing = true;
          // 刷新token的逻辑,这里假设存在一个refreshToken函数
          refreshToken().then((newToken) {
            token = newToken;
            isRefreshing = false;
            requestQueue.forEach((req) => _retryRequest(req, handler));
            requestQueue.clear();
          }).catchError((error) {
            isRefreshing = false;
            // 刷新token失败的处理
            if (handler!= null) {
              handler.reject(DioError(
                response: response,
                error: error,
                type: DioErrorType.other,
              ));
            }
          });
        }
        if (handler!= null) {
          requestQueue.add(response?.requestOptions?? RequestOptions());
        }
      }
    
      Future<String> refreshToken() async {
        // 实际刷新token的逻辑,如调用刷新API
        // 这里假设返回一个新的token字符串
        return 'new_token';
      }
    
      void _retryRequest(RequestOptions options, ErrorInterceptorHandler? handler) {
        options.headers['Authorization'] = 'Bearer $token';
        Dio dio = Dio();
        dio.request<dynamic>(options.path,
            options: options).then((response) {
          if (handler!= null) {
            handler.resolve(response);
          }
        }).catchError((error) {
          if (handler!= null) {
            handler.reject(error);
          }
        });
      }
    }
    
  3. 添加拦截器到Dio实例: 在创建Dio实例时添加认证拦截器:
    Dio dio = Dio();
    dio.interceptors.add(AuthInterceptor());
    

通过上述步骤,使用Dio的拦截器可以统一管理不同API请求的认证头信息,并且在认证信息过期时,能够自动刷新并重新发起原请求,同时也处理了多个请求并发时的情况。