首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

智能的闲时监测机制

  • 24-12-16 12:05
  • 2086
  • 12639
juejin.cn

如何检查线程空闲

在Android冷启动和某些业务场景中,我们期望在主线程不繁忙的情况下请求Api或者初始化SDK等。借助这个策略我们可以很智能的完成一些并不是很重要的任务。很多人马上就想到了MessageQueue.addIdleHandler。

addIdleHandler

Main线程主要用于UI绘制相关任务,Android提供Looper和MessageQueue来管理这些任务,同时提供了会在UI任务不繁忙的回调接口IdleHandler。那么能否给子线程也用呢,不可以的,子线程执行的任务不依赖Looper。

java
代码解读
复制代码
public static interface IdleHandler { /** * 当MessageQueue当前没有任务处理时候会回调,而且huidiao运行在主线程 * return true会不断持续监测和回调 * return false 会remove这个回调,调用一次 */ boolean queueIdle(); }

协程和IdleHandler

知道了api用法我们很容易写出如下代码

kotlin
代码解读
复制代码
Looper.getMainLooper().queue.addIdleHandler { // 执行延迟的任务 false }

当我们有需求例如跟随生命周期销毁,或者添加超时机制那么实现就很麻烦了。但是如果我们借助协程,就会非常简单。首先我们借助suspendCancellableCoroutine实现一个挂起函数, 调用invokeOnCancellation在cancel时候remove回调,使用带有生命周期的协程作用域会在销毁时remove回调。

kotlin
代码解读
复制代码
import kotlinx.coroutines.suspendCancellableCoroutine import kotlin.coroutines.resume suspend fun waitForIdle() = suspendCancellableCoroutine { val queue = Looper.getMainLooper().queue val callback = { it.resume(Unit);false } queue.addIdleHandler(callback) it.invokeOnCancellation { queue.removeIdleHandler(callback) } }

测试延迟执行效果, 主线程的挂起并不是阻塞主线程所以不会ANR:

kotlin
代码解读
复制代码
viewModelScope.launch { // start time waitForIdle() requestRedDot() //end Log.d("requestRedDot", "after: $time") } // requestRedDot - after: 310ms

超时机制 withTimeout

由于这个回调是在主线程不繁忙时候才会回调,我们并不知道它的时间,如果我们有需求最长等待5秒即可执行任务,那么我们可以借助withTimeout系列函数。

kotlin
代码解读
复制代码
val t: T? = withTimeoutOrNull(5.seconds) { // T} //5秒后返回null val t: T = withTimeout(5.seconds) { // T} //5秒后抛出异常

我们需要等待5秒,如果没有执行到回调即可解除addIdleHandler让挂起函数向后执行。

kotlin
代码解读
复制代码
suspend fun awaitIdle(timeout: Duration = 5.seconds) = withTimeoutOrNull(timeout) { waitForIdle() } ?: Unit

测试下注释掉如下代码,来模拟长时间没有回调

kotlin
代码解读
复制代码
... val callback = { //it.resume(Unit);false } // requestRedDot - after: 5000ms

合并

kotlin
代码解读
复制代码
import kotlinx.coroutines.suspendCancellableCoroutine import kotlin.coroutines.resume import kotlin.time.Duration import kotlin.time.Duration.Companion.seconds suspend fun awaitIdle(timeout: Duration = 5.seconds) = withTimeoutOrNull(timeout) { suspendCancellableCoroutine { val queue = Looper.getMainLooper().queue val callback = { it.resume(Unit);false } queue.addIdleHandler(callback) it.invokeOnCancellation { queue.removeIdleHandler(callback) } } }
注:本文转载自juejin.cn的forJrking的文章"https://juejin.cn/post/7448519287130177571"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

140
Android
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top