MST

星途 面试题库

面试题:Flutter网络请求重试机制中的错误处理与策略优化

在Flutter中基于Dio库实现网络请求重试机制时,如何根据不同类型的网络错误(如超时、连接失败、服务器错误等)制定不同的重试策略?请详细说明实现步骤和涉及到的代码逻辑。
18.3万 热度难度
前端开发Flutter

知识考点

AI 面试

面试题答案

一键面试
  1. 引入依赖: 在pubspec.yaml文件中确保已引入dio库:
dependencies:
  dio: ^[具体版本号]

然后运行flutter pub get。 2. 定义重试策略

  • 超时错误重试策略: 通常可以设置一个固定的重试次数,比如3次,每次重试间隔一定时间(如2秒)。
  • 连接失败重试策略: 与超时类似,但可能重试次数可以更多一些,例如5次,重试间隔可适当增加(如3秒)。
  • 服务器错误重试策略: 对于一些常见的服务器错误(如500系列错误),可以尝试较少次数(如2次),间隔时间相对较短(如1秒)。
  1. 实现代码逻辑
import 'package:dio/dio.dart';

class RetryInterceptor extends Interceptor {
  int maxRetryCount = 3;
  Duration retryDelay = const Duration(seconds: 2);

  @override
  void onError(DioError err, ErrorInterceptorHandler handler) async {
    if (err.type == DioErrorType.connectTimeout ||
        err.type == DioErrorType.sendTimeout ||
        err.type == DioErrorType.receiveTimeout) {
      // 超时错误重试
      int retryCount = 0;
      while (retryCount < maxRetryCount) {
        retryCount++;
        await Future.delayed(retryDelay);
        try {
          final response = await err.requestOptions.retryWith();
          return handler.resolve(response);
        } catch (e) {
          if (retryCount == maxRetryCount) {
            return handler.reject(err);
          }
        }
      }
    } else if (err.type == DioErrorType.connectionError) {
      // 连接失败重试
      maxRetryCount = 5;
      retryDelay = const Duration(seconds: 3);
      int retryCount = 0;
      while (retryCount < maxRetryCount) {
        retryCount++;
        await Future.delayed(retryDelay);
        try {
          final response = await err.requestOptions.retryWith();
          return handler.resolve(response);
        } catch (e) {
          if (retryCount == maxRetryCount) {
            return handler.reject(err);
          }
        }
      }
    } else if (err.response != null && (err.response.statusCode! >= 500 && err.response.statusCode! < 600)) {
      // 服务器错误重试
      maxRetryCount = 2;
      retryDelay = const Duration(seconds: 1);
      int retryCount = 0;
      while (retryCount < maxRetryCount) {
        retryCount++;
        await Future.delayed(retryDelay);
        try {
          final response = await err.requestOptions.retryWith();
          return handler.resolve(response);
        } catch (e) {
          if (retryCount == maxRetryCount) {
            return handler.reject(err);
          }
        }
      }
    } else {
      return handler.reject(err);
    }
  }
}

extension RetryExtension on RequestOptions {
  Future<Response> retryWith() async {
    final dio = Dio();
    return dio.request(
      path,
      data: data,
      queryParameters: queryParameters,
      options: this,
    );
  }
}
  1. 使用重试拦截器
void main() async {
  final dio = Dio();
  dio.interceptors.add(RetryInterceptor());
  try {
    final response = await dio.get('https://example.com/api');
    print(response.data);
  } catch (e) {
    print('请求失败: $e');
  }
}

上述代码通过自定义RetryInterceptor拦截器,根据不同类型的DioError制定了不同的重试策略,并通过扩展RequestOptions类实现了重试功能。在main函数中,将RetryInterceptor添加到Dio的拦截器中,从而使网络请求具备重试机制。