Flutter 三方库 dio 与 pull_to_refresh 的鸿蒙化适配指南

欢迎加入开源鸿蒙跨平台社区:→https://openharmonycrossplatform.csdn.net
摘要
本文基于 Flutter for OpenHarmony 技术栈,以设备列表管理场景为例,完整介绍了 dio 网络请求库与 pull_to_refresh 下拉刷新库的鸿蒙化适配实践。从功能实现、性能优化、代码修复到平台验证,提供了一套可直接落地的跨平台开发方案,帮助开发者快速实现兼容开源鸿蒙的高可用 Flutter 应用。
一、项目背景与核心功能
在开源鸿蒙设备管理类应用中,网络请求与列表刷新是高频核心能力。本次适配基于 Flutter 框架,针对设备列表场景,实现了完整的功能闭环:
网络请求能力:使用 dio 库封装了带错误处理与重试机制的网络服务,支持设备列表与详情的拉取
列表交互能力:基于 pull_to_refresh 实现下拉刷新、上拉加载,搭配加载动画与状态提示
搜索与状态管理:支持设备名称 / IP/ID 的实时搜索过滤,覆盖加载中、错误、空数据全场景
UI 与体验优化:使用 Card 组件美化列表项,AppBar 集成搜索框,添加设备状态视觉反馈
二、核心功能实现
2.1 dio 网络请求封装
我们在lib/services/api_service.dart中封装了ApiService类,解决鸿蒙环境下的网络请求适配问题:
实现了通用请求封装,内置重试机制与异常捕获
为设备列表和详情接口添加了缓存策略,减少重复请求
兼容 OpenHarmony 的网络权限与请求限制,确保请求稳定
核心代码示例:

import 'package:dio/dio.dart';

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

  // 缓存存储
  final Map<String, dynamic> _cache = {};

  ApiService._internal() {
    dio = Dio(BaseOptions(
      connectTimeout: const Duration(seconds: 10),
      receiveTimeout: const Duration(seconds: 10),
    ));
    // 添加重试拦截器
    dio.interceptors.add(RetryInterceptor(
      dio: dio,
      retries: 3,
      retryDelays: const [
        Duration(seconds: 1),
        Duration(seconds: 2),
        Duration(seconds: 3),
      ],
    ));
  }

  // 获取设备列表(带缓存)
  Future<List<Device>> getDeviceList({bool refresh = false}) async {
    const cacheKey = 'device_list';
    if (!refresh && _cache.containsKey(cacheKey)) {
      return _cache[cacheKey];
    }
    try {
      final response = await dio.get('/api/devices');
      final list = (response.data['list'] as List).map((e) => Device.fromJson(e)).toList();
      _cache[cacheKey] = list;
      return list;
    } on DioException catch (e) {
      // 统一错误处理
      throw _handleDioError(e);
    }
  }

  Exception _handleDioError(DioException e) {
    switch (e.type) {
      case DioExceptionType.connectionTimeout:
        return Exception("网络连接超时,请检查网络设置");
      case DioExceptionType.receiveTimeout:
        return Exception("服务器响应超时");
      case DioExceptionType.badResponse:
        return Exception("请求失败,状态码:${e.response?.statusCode}");
      default:
        return Exception("网络请求异常,请稍后重试");
    }
  }
}

2.2 pull_to_refresh 列表交互实现
在lib/main.dart中,我们基于pull_to_refresh实现了下拉刷新与上拉加载:

class _DeviceListPageState extends State<DeviceListPage> {
  final RefreshController _refreshController = RefreshController(initialRefresh: false);
  final ApiService _apiService = ApiService();
  List<Device> _deviceList = [];
  bool _isLoading = true;
  String? _errorMsg;
  Timer? _searchDebounceTimer;

  @override
  void initState() {
    super.initState();
    _fetchDeviceList(refresh: true);
  }

  // 下拉刷新
  void _onRefresh() async {
    try {
      await _fetchDeviceList(refresh: true);
      _refreshController.refreshCompleted();
    } catch (e) {
      _refreshController.refreshFailed();
    }
  }

  // 上拉加载更多
  void _onLoading() async {
    try {
      // 模拟分页加载
      await Future.delayed(const Duration(milliseconds: 1000));
      // 若没有更多数据,调用loadNoData()
      _refreshController.loadComplete();
    } catch (e) {
      _refreshController.loadFailed();
    }
  }

  // 带防抖的搜索过滤
  void _onSearchChanged(String keyword) {
    _searchDebounceTimer?.cancel();
    _searchDebounceTimer = Timer(const Duration(milliseconds: 500), () {
      setState(() {
        // 按设备名称、IP、ID过滤列表
        _filteredList = _deviceList.where((device) {
          return device.name.contains(keyword) ||
              device.ip.contains(keyword) ||
              device.id.contains(keyword);
        }).toList();
      });
    });
  }

  @override
  void dispose() {
    _refreshController.dispose();
    _searchDebounceTimer?.cancel(); // 释放定时器,避免内存泄漏
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: TextField(
          decoration: const InputDecoration(
            hintText: '搜索设备名称/IP/ID',
            border: InputBorder.none,
            icon: Icon(Icons.search),
          ),
          onChanged: _onSearchChanged,
        ),
      ),
      body: _buildBody(),
    );
  }

  Widget _buildBody() {
    if (_isLoading) {
      return const Center(child: CircularProgressIndicator());
    }
    if (_errorMsg != null) {
      return Center(child: Text(_errorMsg!));
    }
    if (_filteredList.isEmpty) {
      return const Center(child: Text("暂无设备数据"));
    }
    return SmartRefresher(
      controller: _refreshController,
      enablePullDown: true,
      enablePullUp: true,
      onRefresh: _onRefresh,
      onLoading: _onLoading,
      child: ListView.builder(
        itemCount: _filteredList.length,
        itemBuilder: (context, index) {
          final device = _filteredList[index];
          return Card(
            margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
            child: ListTile(
              leading: Icon(
                Icons.devices_outlined, // 替换不存在的devices_off图标
                color: device.isOnline ? Colors.green : Colors.grey,
              ),
              title: Text(device.name),
              subtitle: Text("IP: ${device.ip} | ID: ${device.id}"),
            ),
          );
        },
      ),
    );
  }
}

三、性能与体验优化
3.1 核心优化点
表格
3.2 关键修复说明
图标兼容性修复:将Icons.devices_off替换为Icons.devices_outlined,解决该图标在鸿蒙环境中不存在的问题
类型错误修复:将Duration(seconds: 0.5)修改为Duration(milliseconds: 500),确保参数类型合规,避免编译错误
四、鸿蒙平台验证
4.1 代码质量检查
执行flutter analyze命令,无语法错误与平台兼容性警告
代码结构清晰,分层明确,符合 Flutter 跨平台开发规范
4.2 构建与运行验证
成功执行flutter build hap命令,无构建错误,生成了兼容开源鸿蒙的 HAP 安装包
应用在鸿蒙设备上可正常运行,网络请求、下拉刷新、搜索过滤等功能均符合预期,无运行崩溃或逻辑异常
4.3 兼容性说明
本次适配使用的dio与pull_to_refresh库均已兼容 Flutter for OpenHarmony 环境,适配过程中未发现平台特有的 API 冲突,所有功能均能在鸿蒙设备上稳定运行。
五、总结与实践建议
本文通过一个完整的设备列表案例,展示了 Flutter 中dio与pull_to_refresh库在开源鸿蒙平台的适配与优化方案。在跨平台开发中,除了基础功能实现,还需要重点关注以下几点:
平台兼容性优先:提前验证三方库在鸿蒙环境的可用性,避免使用平台特有的 API 或图标
性能与体验并重:通过缓存、防抖、资源释放等手段,提升应用在低配置鸿蒙设备上的运行流畅度
完善的状态处理:覆盖加载中、错误、空数据等场景,提升用户体验的完整性
运用实例
运用实例

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐