You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中GetConnect偶现null响应(Android10居多)的原因及解决

问题

使用GetX框架的getConnect调用REST接口并验证响应时,偶现响应为null的情况(大多发生在Android 10设备上)。原本预期每次请求都能得到SUCCESS或FAIL结果,现在出现了null响应,想知道这是GetX包问题、Android版本问题还是其他原因,以及对应的修复方法。


相关代码实现

class ApiServices with DataStorageMixin {

  final Logger log = Logger();
  static GetConnect? _instance;

  ApiServices._() {
    if (_instance == null) {
      _instance = GetConnect(timeout: const Duration(seconds: 10));
      _instance!.httpClient.addRequestModifier<dynamic>((request) {
        log.i("Request method: ${request.method}\nUrl: ${request.url}");
        log.i("Request header: ${request.headers}");
        return request;
      });
      _instance!.httpClient.addResponseModifier((request, response) {
        log.i("Response is : ${response.status.code}\nBody: ${response.body}");
        return response;
      });
    }
  }

  factory ApiServices.instance() => ApiServices._();

  void validateResponse({
    required Response? response,
    required Callback<Map<String, dynamic>> onSuccess,
    required Callback<Map<String, dynamic>> onRequestError,
    required Callback<Map<String, dynamic>> onServerError,
  }) {
    print('RB --- ${response!.body}');
    if (response!.body != null) {
      Map<String, dynamic> responseBody = response.body;
      if (response.statusCode == 200 || response.statusCode == 201) {
        bool isSuccessResponse = responseBody['err'] == CODE_SUCCESS ||
            responseBody['err'] == CODE_NEW_USER ||
            responseBody['err'] == CODE_REGISTERED_USER ||
            responseBody['err'] == CODE_CREATE;
        if (isSuccessResponse) {
          onSuccess(responseBody);
        } else {
          onRequestError(responseBody);
        }
      } else {
        onServerError(responseBody);
      }
    }
  }

  Future<void> apiPostCall({
    String? bearerToken,
    required String endPoint,
    bool isFullEndPoint = false,
    Map<String, dynamic>? data,
    required Callback<Map<String, dynamic>> onSuccess,
    required Callback<Map<String, dynamic>> onRequestError,
    required Callback<Map<String, dynamic>> onServerError,
  }) async {
    // try {
    Response? response = await _instance!.post(
      isFullEndPoint ? endPoint : '$BASE_URL$endPoint',
      data,
      headers: await getHeader(
        url: endPoint,
        bearerToken: bearerToken,
      ),
    );
    validateResponse(
      response: response,
      onSuccess: onSuccess,
      onRequestError: onRequestError,
      onServerError: onServerError,
    );
    // } catch (e) {
    //   onServerError({'error': e});
    // }
  }
}

问题现象

在validateResponse()方法中打印response.body时偶现null值,部分场景下接口返回无响应体的结果。


分析与解决方案

可能的原因

  1. 网络异常未捕获:当前代码注释了try-catch块,请求过程中出现的连接中断、超时、DNS解析失败等异常不会被处理,直接返回状态异常的Response,其body为null。
  2. Android 10网络限制:Android 10对后台网络访问有更严格的限制,若应用在后台发起请求,可能被系统中断,导致未完整接收响应。
  3. 单例初始化竞态:现有单例实现存在线程安全隐患,多线程同时初始化时可能导致GetConnect实例状态异常,影响请求处理。
  4. 服务器端异常响应:部分场景下服务器返回无响应体的错误(如5xx状态码但无内容),Android 10的网络栈对这类响应的处理逻辑与其他版本存在差异。

修复步骤

  1. 恢复并完善异常捕获
    重新启用apiPostCall中的异常捕获,处理请求过程中出现的所有异常:

    Future<void> apiPostCall({
      String? bearerToken,
      required String endPoint,
      bool isFullEndPoint = false,
      Map<String, dynamic>? data,
      required Callback<Map<String, dynamic>> onSuccess,
      required Callback<Map<String, dynamic>> onRequestError,
      required Callback<Map<String, dynamic>> onServerError,
    }) async {
      try {
        Response? response = await _instance!.post(
          isFullEndPoint ? endPoint : '$BASE_URL$endPoint',
          data,
          headers: await getHeader(
            url: endPoint,
            bearerToken: bearerToken,
          ),
        );
        validateResponse(
          response: response,
          onSuccess: onSuccess,
          onRequestError: onRequestError,
          onServerError: onServerError,
        );
      } catch (e) {
        onServerError({'error': '请求异常: ${e.toString()}'});
      }
    }
    
  2. 完善空值处理逻辑
    在validateResponse中增加对response和response.body为null的处理,避免空指针同时触发错误回调:

    void validateResponse({
      required Response? response,
      required Callback<Map<String, dynamic>> onSuccess,
      required Callback<Map<String, dynamic>> onRequestError,
      required Callback<Map<String, dynamic>> onServerError,
    }) {
      print('RB --- ${response?.body}');
      if (response == null) {
        onServerError({'error': '请求无响应'});
        return;
      }
      if (response.body == null) {
        onServerError({'error': '响应体为空', 'statusCode': response.statusCode});
        return;
      }
      Map<String, dynamic> responseBody = response.body;
      if (response.statusCode == 200 || response.statusCode == 201) {
        bool isSuccessResponse = responseBody['err'] == CODE_SUCCESS ||
            responseBody['err'] == CODE_NEW_USER ||
            responseBody['err'] == CODE_REGISTERED_USER ||
            responseBody['err'] == CODE_CREATE;
        if (isSuccessResponse) {
          onSuccess(responseBody);
        } else {
          onRequestError(responseBody);
        }
      } else {
        onServerError(responseBody);
      }
    }
    
  3. 优化单例实现
    使用线程安全的单例写法,避免竞态条件:

    class ApiServices with DataStorageMixin {
      final Logger log = Logger();
      static late final GetConnect _instance;
      static bool _initialized = false;
    
      ApiServices._() {
        _instance = GetConnect(timeout: const Duration(seconds: 10));
        _instance.httpClient.addRequestModifier<dynamic>((request) {
          log.i("Request method: ${request.method}\nUrl: ${request.url}");
          log.i("Request header: ${request.headers}");
          return request;
        });
        _instance.httpClient.addResponseModifier((request, response) {
          log.i("Response is : ${response.status.code}\nBody: ${response.body}");
          return response;
        });
        _initialized = true;
      }
    
      factory ApiServices.instance() {
        if (!_initialized) {
          ApiServices._();
        }
        return ApiServices._();
      }
    }
    
  4. 适配Android 10网络策略

    • 若接口使用HTTP而非HTTPS,在AndroidManifest.xml的<application>标签中添加android:usesCleartextTraffic="true"。
    • 若应用需要在后台发起请求,可申请REQUEST_IGNORE_BATTERY_OPTIMIZATIONS权限,避免被系统限制网络。
  5. 排查服务器响应格式
    要求服务器保证所有响应(包括错误状态)都返回标准JSON格式的响应体,避免无内容的返回结果。


内容的提问来源于stack exchange,提问作者La Pyae

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 10:17:33