【OpenHarmony/HarmonyOS】项目实战:分布式数据同步与本地优先策略设计
【OpenHarmony/HarmonyOS】项目实战:分布式数据同步与本地优先策略设计
摘要
全场景学习体验的基础是数据连续:手机上背过的单词,平板上应该能继续;今天完成的复习,另一个设备不应该重复提醒。本文结合「英语视界 YingYu」项目,分享如何设计分布式数据同步与本地优先策略。🔄
项目中已经有 DistributedSync.ets、YingYuPreferences.ts、StorageService.ts 和 EntryAbility.ets 的跨端续接能力。本文会围绕这些代码展开,并补充冲突处理和数据分层设计。
一、为什么要本地优先?
学习 App 不能完全依赖网络:
- 用户可能在地铁、学校等弱网环境;
- 背单词和复习需要随时可用;
- 学习数据不应频繁上传;
- 本地响应更快;
- 隐私风险更低。
所以推荐策略是:
本地优先
-> 本地读写
-> 关键状态同步
-> 网络或设备可用时再跨端同步
二、Preferences 封装
项目中使用 YingYuPreferences.ts 封装 Preferences:
let pref: preferences.Preferences | null = null
export function initYingYuUserData(context: common.UIAbilityContext): void {
if (pref) {
return
}
try {
pref = preferences.getPreferencesSync(context, { name: 'yingyu_user_data_v1' })
} catch (e) {
console.error('initYingYuUserData failed:', JSON.stringify(e))
}
}
读取时优先 Preferences:
export function yingyuPrefGet(key: string): string | undefined {
if (pref) {
const v = pref.getSync(key, '') as string
return v.length > 0 ? v : undefined
}
const fallback = AppStorage.get<string>(key)
if (fallback !== undefined && fallback.length > 0) {
return fallback
}
return undefined
}
写入时支持 AppStorage 兜底:
export function yingyuPrefSet(key: string, value: string): void {
if (!pref) {
AppStorage.setOrCreate(key, value)
return
}
pref.putSync(key, value)
void pref.flush()
}
这是一种稳妥的本地持久化封装。
三、分布式 KV 初始化
项目中的分布式同步初始化:
export async function initDistributedStore(context: Context): Promise<void> {
const kvManagerConfig: distributedKVStore.KVManagerConfig = {
bundleName: 'ying.yu.app',
context: context
}
const kvManager = distributedKVStore.createKVManager(kvManagerConfig)
const options: distributedKVStore.Options = {
createIfMissing: true,
encrypt: false,
backup: false,
autoSync: true,
kvStoreType: distributedKVStore.KVStoreType.SINGLE_VERSION,
securityLevel: distributedKVStore.SecurityLevel.S1
}
kvStore = await kvManager.getKVStore<distributedKVStore.SingleKVStore>(
STORE_ID,
options
)
}
关键配置:
autoSync: true:支持自动同步;SINGLE_VERSION:适合轻量键值状态;backup: false:避免不必要备份;SecurityLevel.S1:适合基础学习数据。
四、哪些数据适合同步?
适合同步:
- 用户设置;
- 已学单词 ID;
- 每日目标;
- 成就状态;
- 复习记录摘要;
- 学习进度;
- 自定义生词。
不建议同步:
- 临时 UI 状态;
- 大量缓存;
- 可重新计算的数据;
- 敏感身份信息;
- 未经用户确认的剪贴板内容。
五、跨设备续接数据
项目中 onContinue() 只传必要状态:
onContinue(wantParam: Record<string, Object>): AbilityConstant.OnContinueResult {
const settings = AppStorage.get<string>('yingyu_settings') || ''
const progress = AppStorage.get<string>('yingyu_progress') || ''
const learnedWords = AppStorage.get<string>('yingyu_learned_words') || ''
wantParam['yingyu_settings'] = settings
wantParam['yingyu_progress'] = progress
wantParam['yingyu_learned_words'] = learnedWords
wantParam['yingyu_timestamp'] = Date.now().toString()
return AbilityConstant.OnContinueResult.AGREE
}
目标设备恢复:
if (settings) AppStorage.setOrCreate('yingyu_settings', settings)
if (progress) AppStorage.setOrCreate('yingyu_progress', progress)
if (learnedWords) AppStorage.setOrCreate('yingyu_learned_words', learnedWords)
这体现了“最小必要”原则。
六、建议增加数据版本号
随着项目升级,数据结构可能变化。建议给本地数据增加版本:
interface SyncPayload<T> {
version: number
updatedAt: number
deviceId: string
data: T
}
例如用户设置:
const payload: SyncPayload<UserSettings> = {
version: 1,
updatedAt: Date.now(),
deviceId: currentDeviceId,
data: getUserSettings()
}
这样后续可以做迁移和冲突判断。
七、冲突处理策略
学习数据可能在多个设备上同时修改。常见策略:
1. 最后写入优先
适合设置项:
dailyGoal
notificationsEnabled
soundEnabled
uiVersion
谁更新时间更晚,就采用谁。
2. 集合合并
适合已学单词:
const merged = Array.from(new Set([...localLearned, ...remoteLearned]))
学习过的单词不应该因为设备冲突而丢失。
3. 按日期合并
适合学习进度:
date -> LearningProgress
同一天数据可以取更大值或合并词数。
4. 成就只增不减
成就一旦解锁,不应该因为同步冲突被锁回去。
unlocked = local.unlocked || remote.unlocked
八、同步触发时机
项目当前在后台和销毁时调用同步:
onBackground(): void {
syncToRemote().catch(() => {})
}
onDestroy(): void {
syncToRemote().catch(() => {})
}
后续还可以在这些时机触发:
- 完成今日任务;
- 完成复习;
- 修改设置;
- 添加生词;
- 解锁成就;
- 应用进入后台。
不要每次输入都同步,避免过于频繁。
九、同步状态提示
可以在设置页或个人中心展示同步状态:
interface SyncStatus {
lastSyncAt?: string
syncing: boolean
failed: boolean
message: string
}
文案示例:
- 数据已同步;
- 正在同步学习进度;
- 当前离线,稍后自动同步;
- 同步失败,请稍后重试。
用户知道数据状态,会更安心。
十、隐私注意点
分布式同步也要遵循隐私原则:
- 只同步学习必要数据;
- 不同步敏感身份信息;
- 不同步原始剪贴板内容;
- 不同步完整 AI 输入日志;
- 提供关闭同步入口;
- 提供清除本地数据入口。
学习项目的数据虽然看起来不敏感,但长期学习记录也能反映用户习惯,需要谨慎对待。
十一、小结
本文结合「英语视界 YingYu」项目,梳理了分布式数据同步和本地优先策略:
- 使用 Preferences + AppStorage 做本地持久化;
- 使用 DistributedKVStore 预留跨设备同步;
onContinue()只传必要学习状态;- 设置适合最后写入优先;
- 已学单词适合集合合并;
- 成就状态只增不减;
- 同步应绑定关键学习事件;
- 数据同步必须控制隐私边界。
全场景体验的底层不是“页面能打开”,而是数据能自然跟着用户走。对学习项目来说,本地优先 + 轻量同步,是更稳也更可信的方案。🔄


更多推荐



所有评论(0)