【开源鸿蒙跨平台开发--GitCode Pocket】02. 高性能网络层架构与鸿蒙权限管理

02. 高性能网络层架构与鸿蒙权限管理

项目地址: https://gitcode.com/Goway_Hui/gitcode-pocket

1. 鸿蒙网络通信机制解析

在 Flutter 鸿蒙应用中,网络请求本质上是通过 Dart 的 dart:io 库发起的。Flutter 引擎会将这些 Dart IO 请求桥接到鸿蒙底层的网络栈。

1.1 鸿蒙特有的网络约束

  1. 权限强制声明:必须在 module.json5 中声明 ohos.permission.INTERNET,否则请求会直接抛出 SocketException。
  2. 明文流量限制:默认情况下,鸿蒙系统(类似于 Android 9+)禁止 HTTP 明文请求。虽然 GitCode API 使用 HTTPS,但我们在调试阶段(连接本地 Mock Server)可能需要 HTTP 支持。
    • 解决方案:在 module.json5module 节点配置 "network": { "cleartextTraffic": true }(需 API 11+ 支持)。

2. 基于 Dio 的网络层封装

我们使用 Dio 作为网络库,它在鸿蒙上运行良好。

2.1 ApiClient 设计

单例模式管理 Dio 实例,确保连接池复用。

// lib/core/network/api_client.dart
import 'package:dio/dio.dart';
import 'package:dio/io.dart'; // 用于配置证书忽略等

class ApiClient {
  static final ApiClient _instance = ApiClient._internal();
  factory ApiClient() => _instance;
  
  late final Dio dio;

  ApiClient._internal() {
    dio = Dio(BaseOptions(
      baseUrl: 'https://api.gitcode.com/api/v5',
      connectTimeout: const Duration(seconds: 15),
      receiveTimeout: const Duration(seconds: 15),
      headers: {
        'User-Agent': 'GitCodePocket-Harmony/1.0.0',
        'Accept': 'application/json',
      },
    ));
    
    _setupInterceptors();
    _setupCertificatePinning();
  }
}

2.2 抓包调试配置

在鸿蒙真机上调试时,我们经常需要使用 Charles/Fiddler 抓包。这需要配置代理和忽略证书错误。

  void _setupCertificatePinning() {
    // 仅在调试模式下开启代理
    if (kDebugMode) {
      dio.httpClientAdapter = IOHttpClientAdapter(
        createHttpClient: () {
          final client = HttpClient();
          // 设置代理地址 (Charles 运行的主机 IP)
          client.findProxy = (uri) => 'PROXY 192.168.1.5:8888';
          // 忽略自签名证书错误
          client.badCertificateCallback = 
              (X509Certificate cert, String host, int port) => true;
          return client;
        },
      );
    }
  }

3. 拦截器链 (Interceptor Chain)

拦截器是网络层逻辑解耦的关键。

3.1 统一鉴权拦截器

GitCode API 支持 OAuth 2.0,我们需要在每次请求头中动态注入 Access Token。

class AuthInterceptor extends Interceptor {
  final TokenRepository _tokenRepo;

  AuthInterceptor(this._tokenRepo);

  
  void onRequest(RequestOptions options, RequestInterceptorHandler handler) async {
    final token = await _tokenRepo.getAccessToken();
    if (token != null) {
      options.headers['Authorization'] = 'Bearer $token';
    }
    super.onRequest(options, handler);
  }
}

3.2 响应数据转换器

为了让业务层直接拿到干净的数据,我们可以在拦截器中统一处理 API 响应结构。

// 假设 API 返回结构: { "code": 200, "message": "ok", "data": ... }
class ResponseInterceptor extends Interceptor {
  
  void onResponse(Response response, ResponseInterceptorHandler handler) {
    if (response.statusCode == 200) {
      // 这里可以直接解包,或者透传
      handler.next(response);
    } else {
      handler.reject(
        DioException(
          requestOptions: response.requestOptions,
          error: 'Server Error: ${response.statusCode}',
        ),
      );
    }
  }
}

4. 业务接口定义 (RemoteService)

我们不直接在 UI 层使用 Dio,而是定义具体的 Service 类。

4.1 用户相关接口

class GitcodeRemoteService {
  final Dio _dio;

  GitcodeRemoteService(this._dio);

  // 获取当前登录用户信息
  Future<User> fetchCurrentUser() async {
    try {
      final response = await _dio.get('/user');
      return User.fromJson(response.data);
    } on DioException catch (e) {
      throw ServerException.fromDio(e);
    }
  }
  
  // 获取用户组织
  Future<List<Organization>> fetchOrganizations() async {
    final response = await _dio.get('/user/orgs');
    return (response.data as List)
        .map((e) => Organization.fromJson(e))
        .toList();
  }
}

5. 错误处理模型

鸿蒙应用的网络错误可能来自于底层(如 SocketException 对应鸿蒙的断网状态)。我们需要将这些底层错误转换为 UI 层可读的 Failure 对象。

abstract class Failure {
  final String message;
  Failure(this.message);
}

class NetworkFailure extends Failure {
  NetworkFailure() : super("网络连接异常,请检查鸿蒙设备的网络设置");
}

class ServerFailure extends Failure {
  ServerFailure(String msg) : super(msg);
}

// 异常转换工厂
Failure handleException(dynamic e) {
  if (e is DioException) {
    if (e.type == DioExceptionType.connectionTimeout) {
      return NetworkFailure();
    }
    // 处理 401, 403, 404 等
  }
  return ServerFailure("未知错误");
}

6. 鸿蒙网络状态监听

为了在断网时给出及时反馈,我们需要监听鸿蒙系统的网络状态。
可以使用 connectivity_plus(需确认鸿蒙适配版本)或者通过 MethodChannel 调用鸿蒙原生的 connection 模块。

ArkTS 侧实现 (EntryAbility.ets):

import connection from '@ohos.net.connection';

// 监听网络连接
let netCon = connection.createNetConnection();
netCon.on('netAvailable', (data) => {
  flutterChannel.invokeMethod('onNetworkAvailable');
});
netCon.on('netLost', (data) => {
  flutterChannel.invokeMethod('onNetworkLost');
});

7. 总结

本章我们构建了一个健壮的网络层。虽然 Dio 在鸿蒙上运行流畅,但我们必须注意权限配置、抓包调试的特殊设置以及底层网络状态的监听。

下一章,我们将深入 认证与安全存储,利用鸿蒙系统的加密能力保护用户的 Token。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值