如何在HTTP请求回调后更新WearOS Tile?
解决方案:在Wear OS Tile中异步获取HTTP数据并返回最新Tile
核心思路
直接在onTileRequest的协程作用域内等待HTTP请求完成,再返回包含最新数据的Tile,彻底避开requestUpdate的20秒限制。关键是把传统Callback式的HTTP请求转换成协程挂起函数,适配协程的异步流程。
步骤1:将Callback请求封装为挂起函数
如果你的EnergyRetriever基于Retrofit,可以直接改用Retrofit的Coroutine支持(定义返回Deferred<EnergyResult>或suspend fun);如果是自定义Callback请求,用suspendCancellableCoroutine手动封装:
// 封装挂起函数版本的API请求 private suspend fun getEnergyUpdateSuspend(): EnergyResult? { return suspendCancellableCoroutine { continuation -> val call = repoRetriever.getEnergyUpdate(object : Callback<EnergyResult> { override fun onFailure(call: Call<EnergyResult>?, t: Throwable?) { Log.e("GoalsTileService", "API请求失败: ${t?.message}") continuation.resume(null) } override fun onResponse(call: Call<EnergyResult>?, response: Response<EnergyResult>?) { val energyResult = if (response?.isSuccessful == true) response.body() else null energyResult?.let { Log.i("GoalsTileService", "请求成功: ${it.time} - ${it.consumption}kW") EnergyRepository.setEnergy(it) } continuation.resume(energyResult) } }) // 协程取消时同步取消网络请求,避免资源浪费 continuation.invokeOnCancellation { call?.cancel() } } }
步骤2:修改onTileRequest,等待请求完成后构建Tile
在onTileRequest的协程中,先拿本地旧数据兜底,再尝试获取最新数据,最终用拿到的有效数据构建Tile:
override fun onTileRequest(requestParams: TileRequest) = serviceScope.future { val deviceParams = requestParams.deviceParameters!! var energyResult = EnergyRepository.getEnergy() // 旧数据兜底 if (isNetworkConnected()) { // 异步等待请求完成,更新为最新数据 val latestResult = getEnergyUpdateSuspend() latestResult?.let { energyResult = it } } // 用最终数据构建并返回Tile Tile.builder() .setResourcesVersion(RESOURCES_VERSION) .setFreshnessIntervalMillis(5 * 60 * 1000) .setTimeline( Timeline.builder().addTimelineEntry( TimelineEntry.builder().setLayout( Layout.builder().setRoot( layout(energyResult!!, deviceParams) ) ) ) ).build() }
关键说明
- 避开
requestUpdate限制:直接在本次onTileRequest流程返回最新数据,无需触发二次更新 - 非阻塞异步等待:挂起函数不会阻塞线程,完全符合Wear OS Tile的异步要求
- 容错兜底:网络请求失败时,依然用本地缓存的旧数据渲染,保证Tile可用性
内容的提问来源于stack exchange,提问作者Toumal
相关产品推荐
相关产品推荐

