地铁里没信号是常态。如果在没网的时候,用户点击"发布评论"直接弹一个"网络异常",他们的第一反应绝对是卸载。现代应用架构的标准是"离线优先":无论有没有网,操作立刻在本地完成,剩下的交给后台悄悄同步。
把本地数据库当成唯一真相
传统的写法是:点击发布 -> 转圈圈 -> 发请求 -> 成功 -> 把数据加进 UI 数组。这套逻辑在弱网下必死无疑。
离线优先的核心原则是:UI 永远只认本地数据,网络请求只是后台的异步动作。
用户在输入框敲完字,点击发布:
-
立刻往本地的 RDB(关系型数据库)里插入一条记录,状态标记为
待同步。 -
UI 监听数据库的变化,立刻刷新列表,显示刚刚发布的内容。
-
触发后台同步任务,去跟服务器交互。
用户根本感觉不到网络的存在,体验极度丝滑。
设计可靠的消息队列
我们不能直接盲发请求,必须建立一个本地同步队列表。
sql
CREATE TABLE IF NOT EXISTS sync_queue (
id INTEGER PRIMARY KEY AUTOINCREMENT,
action_type TEXT, -- 如 INSERT, UPDATE, DELETE
payload TEXT, -- 序列化后的 JSON 数据
retry_count INTEGER DEFAULT 0,
created_at INTEGER
);
当网络恢复时,后台任务从队列里按顺序取出操作,批量发送给服务器。如果发送成功,就删掉队列记录,并更新业务表的状态为 已同步。如果失败,就增加 retry_count。
并发控制的警示
在触发同步时,必须加锁。如果用户不停地在操作,而每一次操作都触发一次同步任务,服务器会被你的并发请求打爆。
typescript
let isSyncing = false;
async function triggerSync() {
if (isSyncing) return; // 锁住,避免并发
isSyncing = true;
try {
// 取出队列数据发送请求...
} finally {
isSyncing = false;
// 如果还有积压数据,继续下一轮
checkAndSyncNext();
}
}
网络状态监听与幂等性防御
必须利用 @ohos.net.connection 监听系统的网络事件。一旦触发 netAvailable,立刻唤醒同步引擎。
这里有一个极度危险的边缘场景:客户端发出了请求,服务器处理成功了,但在返回响应时网络断了。客户端认为失败,下次重试时会再次发送同样的请求,导致服务器出现两条重复的数据。
解决办法: 在客户端生成唯一的业务 UUID,跟请求一起发给服务器。服务器收到请求后,先查库里有没有这个 UUID,有就直接丢弃,没有才执行落库。这就叫接口幂等性,是离线架构的生命线。
写一个极简的备忘录应用。开启飞行模式,疯狂添加十条备忘录。然后关闭飞行模式,观察备忘录是怎么在后台自动同步到本地服务端的,并查一下数据库里的状态变化。