logo

Android网络请求日志封装与接口调用最佳实践

作者:半吊子全栈工匠2025.09.25 16:20浏览量:0

简介:本文详细阐述Android开发中网络接口调用日志封装的方法与接口调用代码优化技巧,提供可复用的日志工具类实现及接口调用最佳实践。

Android网络请求日志封装与接口调用最佳实践

在Android开发中,网络接口调用是连接服务端的核心环节。合理的日志封装不仅能提升调试效率,还能为线上问题追踪提供关键数据。本文将从日志封装设计、接口调用代码优化、异常处理三个维度展开详细讨论。

一、日志封装的核心价值与设计原则

1.1 日志分级的必要性

Android日志系统提供V、D、I、W、E五个级别,网络请求日志应遵循分级原则:

  • DEBUG级别:记录请求参数、响应数据等详细信息
  • INFO级别:记录关键节点(请求开始/结束)
  • ERROR级别:记录异常信息及错误码
  1. public class HttpLogger {
  2. private static final String TAG = "HttpLogger";
  3. public static void d(String message) {
  4. if (BuildConfig.DEBUG) {
  5. Log.d(TAG, message);
  6. }
  7. }
  8. public static void e(String message, Throwable tr) {
  9. Log.e(TAG, message, tr);
  10. }
  11. }

1.2 敏感信息脱敏处理

生产环境日志需避免记录明文密码、token等敏感信息。可采用正则表达式替换:

  1. public static String maskSensitiveInfo(String json) {
  2. // 示例:脱敏token字段
  3. Pattern pattern = Pattern.compile("\"token\":\"[^\"]*\"");
  4. Matcher matcher = pattern.matcher(json);
  5. return matcher.replaceAll("\"token\":\"***\"");
  6. }

1.3 性能关键指标记录

建议记录以下性能指标:

  • DNS解析时间
  • TCP连接建立时间
  • 请求总耗时
  • 数据压缩率

二、接口调用代码的标准化实现

2.1 封装基础请求类

  1. public abstract class BaseHttpRequest {
  2. protected String baseUrl;
  3. protected Map<String, String> headers;
  4. public BaseHttpRequest(String baseUrl) {
  5. this.baseUrl = baseUrl;
  6. this.headers = new HashMap<>();
  7. addDefaultHeaders();
  8. }
  9. private void addDefaultHeaders() {
  10. headers.put("Content-Type", "application/json");
  11. headers.put("Accept", "application/json");
  12. }
  13. public abstract void execute();
  14. }

2.2 OkHttp集成最佳实践

  1. public class OkHttpManager {
  2. private static OkHttpClient client;
  3. static {
  4. client = new OkHttpClient.Builder()
  5. .connectTimeout(10, TimeUnit.SECONDS)
  6. .readTimeout(10, TimeUnit.SECONDS)
  7. .writeTimeout(10, TimeUnit.SECONDS)
  8. .addInterceptor(new LoggingInterceptor())
  9. .build();
  10. }
  11. public static Call enqueueRequest(Request request, Callback callback) {
  12. return client.newCall(request).enqueue(callback);
  13. }
  14. }

2.3 请求日志拦截器实现

  1. public class LoggingInterceptor implements Interceptor {
  2. @Override
  3. public Response intercept(Chain chain) throws IOException {
  4. Request request = chain.request();
  5. long startTime = System.nanoTime();
  6. // 打印请求信息
  7. HttpLogger.d(String.format("发送请求: %s %nHeaders:%s",
  8. request.url(),
  9. request.headers()));
  10. Response response = chain.proceed(request);
  11. long endTime = System.nanoTime();
  12. // 打印响应信息
  13. ResponseBody responseBody = response.body();
  14. String responseString = responseBody.string();
  15. HttpLogger.d(String.format("接收响应: %s %n耗时:%dms %n响应:%s",
  16. response.request().url(),
  17. (endTime - startTime) / 1e6d,
  18. maskSensitiveInfo(responseString)));
  19. return response.newBuilder()
  20. .body(ResponseBody.create(responseBody.contentType(), responseString))
  21. .build();
  22. }
  23. }

三、异常处理与重试机制

3.1 异常分类处理

  1. public enum HttpErrorType {
  2. NETWORK_UNAVAILABLE,
  3. TIMEOUT,
  4. SERVER_ERROR,
  5. PARSE_ERROR,
  6. UNKNOWN
  7. }
  8. public static HttpErrorType parseErrorType(Throwable tr) {
  9. if (tr instanceof SocketTimeoutException) {
  10. return TIMEOUT;
  11. } else if (tr instanceof ConnectException) {
  12. return NETWORK_UNAVAILABLE;
  13. } else if (tr instanceof HttpException) {
  14. return SERVER_ERROR;
  15. } else {
  16. return UNKNOWN;
  17. }
  18. }

3.2 指数退避重试策略

  1. public class RetryInterceptor implements Interceptor {
  2. private static final int MAX_RETRY_COUNT = 3;
  3. private static final long INITIAL_DELAY_MS = 1000;
  4. @Override
  5. public Response intercept(Chain chain) throws IOException {
  6. Request request = chain.request();
  7. int retryCount = 0;
  8. IOException exception = null;
  9. while (retryCount < MAX_RETRY_COUNT) {
  10. try {
  11. Response response = chain.proceed(request);
  12. if (response.isSuccessful()) {
  13. return response;
  14. }
  15. throw new HttpException(response);
  16. } catch (IOException e) {
  17. exception = e;
  18. long delayMs = INITIAL_DELAY_MS * (long) Math.pow(2, retryCount);
  19. Thread.sleep(delayMs);
  20. retryCount++;
  21. }
  22. }
  23. throw exception;
  24. }
  25. }

四、生产环境优化建议

4.1 日志采样策略

  1. public class LogSampler {
  2. private static final double SAMPLE_RATE = 0.1; // 10%采样率
  3. public static boolean shouldLog() {
  4. return Math.random() < SAMPLE_RATE;
  5. }
  6. }

4.2 离线日志存储方案

  1. public class DiskLogWriter {
  2. public static void writeLog(String log) {
  3. ExecutorService executor = Executors.newSingleThreadExecutor();
  4. executor.execute(() -> {
  5. try (FileOutputStream fos = new FileOutputStream("http_logs.txt", true)) {
  6. fos.write((log + "\n").getBytes());
  7. } catch (IOException e) {
  8. HttpLogger.e("写入日志失败", e);
  9. }
  10. });
  11. }
  12. }

五、完整调用示例

  1. public class UserApi {
  2. private static final String USER_API = "/api/user";
  3. public void getUserInfo(String userId, Callback callback) {
  4. HttpUrl url = HttpUrl.parse(baseUrl + USER_API)
  5. .newBuilder()
  6. .addQueryParameter("userId", userId)
  7. .build();
  8. Request request = new Request.Builder()
  9. .url(url)
  10. .get()
  11. .build();
  12. OkHttpManager.enqueueRequest(request, new Callback() {
  13. @Override
  14. public void onFailure(Call call, IOException e) {
  15. HttpErrorType errorType = HttpErrorType.parseErrorType(e);
  16. callback.onFailure(errorType, e.getMessage());
  17. }
  18. @Override
  19. public void onResponse(Call call, Response response) throws IOException {
  20. if (response.isSuccessful()) {
  21. UserInfo userInfo = new Gson().fromJson(
  22. response.body().string(),
  23. UserInfo.class);
  24. callback.onSuccess(userInfo);
  25. } else {
  26. callback.onFailure(
  27. HttpErrorType.SERVER_ERROR,
  28. "服务器错误: " + response.code());
  29. }
  30. }
  31. });
  32. }
  33. }

六、进阶优化方向

  1. 请求合并:相同域名的请求可合并发送
  2. 缓存策略:实现GET请求的本地缓存
  3. 多端适配:根据网络状态自动调整超时时间
  4. 链路追踪:集成TraceID实现全链路日志关联

通过系统化的日志封装和标准化的接口调用实现,可以显著提升Android应用的网络请求稳定性和问题排查效率。建议开发者根据实际业务需求,在上述方案基础上进行定制化扩展。

相关文章推荐

发表评论