ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

《HarmonyOS 7 精准碰一碰跨设备协作开发实战》07:异常恢复、状态机与CrossDrop工程收尾【鸿蒙心迹】

《HarmonyOS 7 精准碰一碰跨设备协作开发实战》07:异常恢复、状态机与CrossDrop工程收尾【鸿蒙心迹】 前六篇我们一路做下来功能都有了。但真用起来呢传到一半App退了怎么办窗口关了怎么办URI失效了怎么办这一篇把这些问题收口。写到这里CrossDrop已经有了精准分享、触点识别、区域路由、多窗口、多文件、业务指令、多设备并发。看起来挺完整。但我自己测的时候发现一堆问题传到一半用户直接把App划掉了。窗口关了任务还在后台跑。文件URI过期了打开失败。用户碰了两次同一个任务传了两遍。切到后台再回来之前的任务状态全丢了。这些问题不解决Demo就是Demo真用起来全是bug。这一篇做工程收口。一、TransferStateMachine统一状态机前面我们零散地定义了一些状态。这一篇统一起来。一个任务从开始到结束要经历这些状态IDLE → RECEIVED → VALIDATING → PROCESSING → COMPLETED中间任何一步失败都可能进入FAILED → RETRYING用户取消进入CANCELLED关键是状态迁移要合法。不能从COMPLETED再跳回PROCESSING不能从IDLE直接跳到COMPLETED。这段代码解决什么问题任务状态机。文件state/TransferStateMachine.ets用途统一管理任务状态迁移接入位置每个TransferTask持有enumTransferState{IDLEidle,RECEIVEDreceived,// 已接收VALIDATINGvalidating,// 校验中PROCESSINGprocessing,// 处理中COMPLETEDcompleted,// 完成FAILEDfailed,// 失败RETRYINGretrying,// 重试中CANCELLEDcancelled// 已取消}classTransferStateMachine{privatestate:TransferStateTransferState.IDLE;// 合法状态迁移表privatevalidTransitions:RecordTransferState,TransferState[]{[TransferState.IDLE]:[TransferState.RECEIVED,TransferState.CANCELLED],[TransferState.RECEIVED]:[TransferState.VALIDATING,TransferState.CANCELLED],[TransferState.VALIDATING]:[TransferState.PROCESSING,TransferState.FAILED,TransferState.CANCELLED],[TransferState.PROCESSING]:[TransferState.COMPLETED,TransferState.FAILED,TransferState.CANCELLED],[TransferState.FAILED]:[TransferState.RETRYING,TransferState.CANCELLED],[TransferState.RETRYING]:[TransferState.VALIDATING,TransferState.CANCELLED],[TransferState.COMPLETED]:[],[TransferState.CANCELLED]:[]};canTransitionTo(newState:TransferState):boolean{returnthis.validTransitions[this.state].includes(newState);}transitionTo(newState:TransferState):boolean{if(this.canTransitionTo(newState)){this.statenewState;returntrue;}console.warn(非法状态迁移this.state → newState);returnfalse;}getState():TransferState{returnthis.state;}}二、任务持久化App退了也能恢复最大的问题是App退了任务状态全丢了。解决办法把任务状态持久化到本地。每次状态变化都存到RDB或Preferences里。App重新启动时读出来恢复未完成的任务。这段代码解决什么问题任务持久化。文件persist/TaskRepository.ets用途任务状态本地持久化接入位置任务状态变化时调用classTaskRepository{// 保存任务状态asyncsaveTask(task:TransferTask){letstoreawaitrelationalStore.getRdbStore(...);awaitstore.executeSql(INSERT OR REPLACE INTO tasks (id, uri, state, progress, retry_count) VALUES (?, ?, ?, ?, ?),[task.id,task.uri,task.stateMachine.getState(),task.progress,task.retryCount]);}// 加载所有未完成任务asyncloadPendingTasks():PromiseTransferTask[]{letstoreawaitrelationalStore.getRdbStore(...);letresultawaitstore.querySql(SELECT * FROM tasks WHERE state NOT IN (completed, cancelled));lettasks:TransferTask[][];while(result.goToNextRow()){lettasknewTransferTask(result.getString(0),result.getString(1));task.progressresult.getDouble(3);task.retryCountresult.getLong(4);tasks.push(task);}returntasks;}// App重启后恢复asyncrestoreOnStartup(){letpendingawaitthis.loadPendingTasks();console.info(恢复未完成任务pending.length个);for(lettaskofpending){// 重新加入队列继续处理taskQueue.addTask(task);}}}三、资源释放该清的都清掉最后一个问题资源泄漏。Listener没注销、Session没关闭、Buffer没释放——这些都会慢慢耗内存。App退出、窗口关闭、任务完成时都要清理注销所有状态监听关闭所有DeviceSession释放未使用的Buffer取消还在跑的异步任务四、整个连载回顾七篇下来我们做了一条完整链路01能传——搭好CrossDrop工程骨架实现第一条完整链路。02知道碰哪里——屏幕坐标到应用坐标的转换。03知道碰哪个窗口——多窗口识别与路由。04能传很多——多文件任务队列并发控制。05能传业务指令——传输层和业务层解耦。06能同时传多设备——每台设备独立Session。07能稳定运行——状态机、持久化、资源释放。从碰一下传文件到碰哪传哪、多窗口、多文件、多设备、稳定可靠这就是完整的跨设备协作工作台。最终总结做跨设备分享看起来就是传个文件这么简单。真做下来从坐标转换、窗口识别、任务队列、业务协议、多设备并发到最后状态机和持久化每一层都有工程问题。这也是做系统级能力的乐趣不是调个API就完了而是要把传输、路由、状态、资源整个链路想清楚。
返回列表