Kotlin中点击按钮每秒刷新自定义View并支持启停如何实现?
实现方案
方案一:Kotlin协程(推荐,无需手动处理内存泄漏)
Kotlin协程配合lifecycleScope可以自动跟随页面生命周期销毁,不会出现任务泄漏问题。
先在Activity/Fragment中声明全局变量:
// 刷新状态标记 private var isRefreshing = false // 持有刷新协程任务 private var refreshJob: Job? = null // 你的两个自定义View实例,需先和xml布局绑定 private lateinit var view1: myView1 private lateinit var view2: myView2
按钮点击逻辑:
// 替换为你的按钮id controlBtn.setOnClickListener { isRefreshing = !isRefreshing if (isRefreshing) { refreshJob = lifecycleScope.launch { while (isActive) { // 主线程调用invalidate触发onDraw view1.invalidate() view2.invalidate() // 间隔1秒 delay(1000L) } } } else { // 终止协程,停止刷新 refreshJob?.cancel() refreshJob = null } }
方案二:Handler + Runnable(兼容低版本逻辑)
如果需要兼容不支持协程的旧项目,可以用主线程Handler实现定时任务。
声明全局变量:
// 绑定主线程Looper,确保任务在主线程执行 private val refreshHandler = Handler(Looper.getMainLooper()) private val refreshTask = object : Runnable { override fun run() { view1.invalidate() view2.invalidate() // 间隔1秒后再次执行任务 refreshHandler.postDelayed(this, 1000L) } } private var isRefreshing = false
按钮点击逻辑:
controlBtn.setOnClickListener { isRefreshing = !isRefreshing if (isRefreshing) { // 立即启动第一次刷新 refreshHandler.post(refreshTask) } else { // 移除待执行任务,终止循环 refreshHandler.removeCallbacks(refreshTask) } }
页面销毁时主动清理任务避免内存泄漏:
override fun onDestroy() { super.onDestroy() refreshHandler.removeCallbacks(refreshTask) }
之前invalidate不生效的常见原因
- 调用
invalidate的代码运行在子线程:Android仅允许主线程更新UI,子线程调用不会触发重绘,甚至会抛出异常 - 自定义View宽高为0:如果布局中自定义View的宽高计算结果为0,
onDraw方法不会被回调,可先设置固定宽高验证 - 调用
invalidate的对象不是当前页面渲染的View实例:确认你调用方法的View和布局绑定的是同一个实例
内容的提问来源于stack exchange,提问作者Klaudia
相关产品推荐
相关产品推荐

