如何检测Complication被移除或替换?避免切换表盘误删数据
检测Complication被移除/覆盖的时机并清理关联数据
一、准确区分「非活跃」与「被移除/覆盖」
onComplicationDeactivated会在切换表盘、Complication暂时不可见时触发,但这并非真正的移除操作。要精准判断Complication是否被移除或覆盖,可在该方法中结合ComplicationManager的活跃列表做二次验证:
override fun onComplicationDeactivated(complicationInstanceId: Int) { super.onComplicationDeactivated(complicationInstanceId) // 延迟1秒检查,规避切换表盘时的系统状态更新延迟 Handler(Looper.getMainLooper()).postDelayed({ val activeComplications = complicationManager.activeComplications val isStillActive = activeComplications.any { it.id == complicationInstanceId } if (!isStillActive) { // 确认Complication已被移除/覆盖,执行数据清理 deleteComplicationData(complicationInstanceId) } }, 1000) }
二、处理complicationInstanceId变化导致的冗余数据
用户移除并重新添加Complication时,新实例会生成新的complicationInstanceId,旧ID对应的数据会残留,可通过两种方式清理:
1. 启动时批量清理
在ComplicationDataSourceService启动时,对比本地保存的所有数据ID与当前活跃Complication的ID,删除无效数据:
override fun onCreate() { super.onCreate() val activeIds = complicationManager.activeComplications.map { it.id }.toSet() val savedIds = getAllSavedComplicationIds() // 从本地存储获取所有已保存的ID val invalidIds = savedIds.filter { !activeIds.contains(it) } invalidIds.forEach { deleteComplicationData(it) } }
2. 为多实例分配稳定的唯一标识
如果需要同一Complication在不同插槽/表盘下独立存储数据,不要仅依赖complicationInstanceId,可结合表盘ID+插槽位置生成稳定标识:
override fun onComplicationActivated(complicationInstanceId: Int, complicationType: Int) { super.onComplicationActivated(complicationInstanceId, complicationType) val complicationInfo = complicationManager.getComplicationInfo(complicationInstanceId) val watchFaceId = complicationInfo?.watchFaceComponentName?.flattenToString() val slotId = complicationInfo?.slotId // 生成稳定的唯一标识,不受移除重加操作影响 val uniqueInstanceId = "$watchFaceId:$slotId" // 保存数据时关联该标识,替代complicationInstanceId saveComplicationData(uniqueInstanceId, yourData) }
三、额外注意事项
- 延迟检查的时间可根据实际场景调整,避免过短导致系统状态未更新完成,或过长导致用户切回原表盘时误删数据。
- 数据操作建议使用SharedPreferences、Room等方案,保证持久化操作的原子性。
- 当其他Complication覆盖当前插槽时,原实例的ID会从活跃列表中消失,同样会触发上述清理逻辑。
内容的提问来源于stack exchange,提问作者dect
相关产品推荐
相关产品推荐

