Flutter实现有无网络均可同步向服务器发数据的方案及http/dio选型咨询
Flutter离线数据缓存同步实现方案
具体实现思路
- 网络状态实时监听
引入connectivity_plus第三方库,全局监听应用的网络状态变化,区分无网络、蜂窝网络、WiFi网络三种常见状态,作为请求逻辑分支判断的依据。
- 网络状态实时监听
- 待同步数据本地存储
选择合适的本地持久化方案:结构化的待同步数据优先用Isar或Hive这类轻量NoSQL数据库,不推荐用shared_preferences存储队列类数据。每个待同步任务需要存储的核心字段包括:唯一ID、请求目标地址、请求方法、请求参数/body、请求头、已重试次数、数据创建时间。
- 待同步数据本地存储
- 核心请求逻辑封装
所有业务请求统一走封装后的请求方法:
- 触发请求时先判断当前网络状态,网络正常则直接发起请求
- 请求成功则直接返回结果,流程结束
- 请求失败时如果是网络异常、服务端5xx类可重试错误,就将当前请求的全量信息写入本地待同步队列
- 如果当前无网络,直接把请求写入待同步队列,不发起实际网络请求
- 核心请求逻辑封装
- 自动同步触发机制
两个触发同步的时机:
- 监听到网络状态从无网络切换为有网络时,立刻启动同步任务
- 应用从后台切回前台时,主动查询本地是否存在待同步任务,存在则启动同步
同步执行规则:按数据创建时间先后顺序执行请求,避免业务逻辑出现顺序错乱;单条请求同步成功后删除本地对应的待同步记录;请求失败时如果未到预设的最大重试次数则保留记录,等待下一次同步触发,超过最大重试次数的任务标记为失败,可通知用户手动处理。
- 自动同步触发机制
- 冲突处理规则
提前根据业务场景定义冲突解决规则:如果本地修改的数据在离线期间服务端也产生了更新,可选择服务端版本优先、本地版本优先,或者弹出提示让用户选择合并方案,避免出现数据覆盖问题。
- 冲突处理规则
网络请求库选型建议
优先选择dio,只有当你的项目非常轻量、仅存在个位数的简单请求时才考虑用官方http库,原因如下:
- 官方
http库的优势是体积轻量、API简单无额外封装,但是没有内置拦截器、重试机制、请求取消等常用能力,如果要实现离线缓存同步的全局逻辑,需要手动封装的代码量非常大。 dio自带全局拦截器,可以直接在错误拦截回调中统一捕获网络异常的请求,自动写入本地待同步队列,不用逐个接口做判断,开发效率高;同时内置重试、请求取消、进度监听、FormData处理等能力,后续业务扩展也更方便,配套的周边生态也更完善。
给一个极简的dio全局拦截器示例供参考:
import 'package:dio/dio.dart'; final dio = Dio(); dio.interceptors.add(InterceptorsWrapper( onError: (DioException error, ErrorInterceptorHandler handler) async { // 捕获网络异常类错误 if (error.type == DioExceptionType.connectionError || error.type == DioExceptionType.connectionTimeout || error.type == DioExceptionType.receiveTimeout) { // 把当前请求信息存入本地待同步队列 await insertPendingRequest( requestPath: error.requestOptions.path, method: error.requestOptions.method, data: error.requestOptions.data, headers: error.requestOptions.headers, createTime: DateTime.now().millisecondsSinceEpoch ); } return handler.next(error); }, ));
内容的提问来源于stack exchange,提问作者Osama Mohamad
相关产品推荐
相关产品推荐

