C# Xamarin.Forms HttpClient偶发断网场景请求持久化与重试方案咨询
解决方案:Xamarin.Forms 离线HTTP请求持久化重试机制实现
核心实现思路
要满足你提到的无网暂存、重启不丢、网络恢复自动重试的需求,核心要落地两个能力:请求的持久化本地存储、网络状态联动的自动重试调度,以下是可直接落地的实现方案:
分步实现步骤
- 第一步:实现待执行请求的本地持久化
选用Xamarin生态通用的SQLite-net-pcl库做本地存储,所有待执行的请求都会序列化后存入SQLite,设备关机、应用卸载前数据都不会丢失。请求存储的实体类参考如下:
注意:如果请求头里存了鉴权Token等敏感信息,需要加密后再存入本地,避免明文泄露。public class PendingHttpRequest { [PrimaryKey, AutoIncrement] public int Id { get; set; } public string HttpMethod { get; set; } // 存GET/POST/PUT/DELETE等 public string RequestUrl { get; set; } public string HeadersJson { get; set; } // 请求头序列化为JSON存储 public string BodyJson { get; set; } // 请求体序列化为JSON存储 public int RetryCount { get; set; } = 0; public int MaxRetryCount { get; set; } = 3; // 可根据业务自定义 public DateTime CreateTime { get; set; } = DateTime.Now; public bool IsExecuting { get; set; } = false; public string IdempotentKey { get; set; } // 幂等键,防重复提交 } - 第二步:封装全局HTTP请求代理
所有业务层的HTTP请求统一走代理服务,不要直接调用HttpClient:- 先调用Xamarin.Essentials的
Connectivity类判断当前网络状态 - 如果网络可用,直接发起请求,请求成功直接返回结果给业务层
- 如果网络不可用,直接把请求参数序列化后写入本地SQLite,根据业务需求返回 pending 状态或者本地缓存数据即可
网络状态判断参考代码:
var networkAccess = Connectivity.NetworkAccess; bool hasValidNetwork = networkAccess == NetworkAccess.Internet; - 先调用Xamarin.Essentials的
- 第三步:实现自动重试调度逻辑
两个触发重试的时机要同时覆盖:- 应用启动时(App.xaml.cs的
OnStart生命周期里),主动拉取本地所有未执行、重试次数未达上限的请求,按创建时间升序依次执行 - 注册
Connectivity.ConnectivityChanged事件监听网络变化,当监听到网络恢复为可用状态时,立即触发重试任务
单条请求的重试规则:执行成功就从本地SQLite删除该条记录;执行失败就将重试次数+1更新回本地,等待下一次重试触发;超过最大重试次数的请求可以存入死信队列,根据业务需求触发告警或者人工处理。
- 应用启动时(App.xaml.cs的
- 第四步:边界问题处理
用SemaphoreSlim给重试任务加异步锁,避免同一时间多个重试线程并发执行,导致同一条请求重复提交;对于支付、订单创建等幂等要求高的场景,请求生成时同步生成唯一幂等键存在本地,请求发送时放在头信息传给后端,后端通过幂等键过滤重复请求,避免重试带来的业务异常。
额外优化建议
- 大文件上传类的请求不要把文件内容存在SQLite里,先把文件存在应用沙箱,请求记录里只存文件路径,请求执行成功后再删除本地文件
- 重试间隔采用指数退避策略,第一次失败隔1秒重试,第二次隔2秒,第三次隔4秒,避免瞬间大量重试打垮后端服务
- 本地存储的请求设置过期清理规则,超过7天未执行成功的请求自动清理,避免占用过多本地存储空间
内容的提问来源于stack exchange,提问作者Flea
相关产品推荐
相关产品推荐

