android 之 Kotlin中Handler的使用

在 Android Kotlin 开发中,Handler主要用于​​线程间通信​ ​(如后台线程更新 UI)和​​延迟任务调度​​。以下是关键用法、示例及注意事项,结合最佳实践和内存安全方案:

Kotlin 复制代码
class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding
    // 绑定主线程 Looper
    private val mainHandler = Handler(Looper.getMainLooper())

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        // 在后台线程执行耗时任务
        thread {
            Thread.sleep(2000) // 模拟耗时操作
            // 通过 Handler 切回主线程更新 UI
            mainHandler.post {
                binding.textView.text = "后台任务完成,主线程更新 UI"
            }
        }
    }
}
  • 关键点​ ​:Handler(Looper.getMainLooper())确保任务在主线程执行。

  • ​场景​​:网络请求、数据库读写等后台操作后更新 UI。

2. ​​延迟执行任务​
Kotlin 复制代码
// 延迟 3 秒显示 Toast
mainHandler.postDelayed({
    Toast.makeText(this, "延迟 3 秒执行", Toast.LENGTH_SHORT).show()
}, 3000)

​注意​ ​:时间单位是毫秒(3000ms = 3s

​二、避免内存泄漏(安全写法)​

Handler持有 Activity引用可能导致内存泄漏。解决方案:

​方案 1:静态内部类 + 弱引用​
Kotlin 复制代码
class SafeHandlerActivity : AppCompatActivity() {
    private lateinit var weakHandler: WeakReferenceHandler

    companion object {
        const val MSG_UPDATE_TEXT = 1
    }

    // 静态内部类,不持有外部引用
    class WeakReferenceHandler(activity: SafeHandlerActivity) : Handler(Looper.getMainLooper()) {
        private val weakRef = WeakReference(activity)

        override fun handleMessage(msg: Message) {
            val activity = weakRef.get() ?: return
            when (msg.what) {
                MSG_UPDATE_TEXT -> activity.binding.textView.text = "安全更新文本"
            }
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        weakHandler = WeakReferenceHandler(this)
        // 发送延迟消息
        weakHandler.sendEmptyMessageDelayed(MSG_UPDATE_TEXT, 2000)
    }

    override fun onDestroy() {
        super.onDestroy()
        weakHandler.removeCallbacksAndMessages(null) // 移除所有回调
    }
}
方案 2:结合 Lifecycle​
Kotlin 复制代码
class LifecycleAwareHandler(
    lifecycle: Lifecycle,
    looper: Looper,
    private val callback: (Message) -> Boolean
) : Handler(looper) {

    init {
        lifecycle.addObserver(object : LifecycleObserver {
            @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
            fun onDestroy() {
                removeCallbacksAndMessages(null)
                lifecycle.removeObserver(this)
            }
        })
    }

    override fun handleMessage(msg: Message) {
        if (lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)) {
            callback(msg)
        }
    }
}

优势​ ​:自动在 onDestroy时清理消息

三、替代方案:协程(推荐)​

现代 Android 开发中,协程更简洁且避免内存泄漏:

Kotlin 复制代码
class CoroutineActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        lifecycleScope.launch(Dispatchers.IO) {
            delay(2000) // 后台延迟 2 秒
            withContext(Dispatchers.Main) {
                binding.textView.text = "协程更新 UI"
            }
        }
        // 主线程延迟任务
        lifecycleScope.launch(Dispatchers.Main) {
            delay(3000)
            Toast.makeText(this@CoroutineActivity, "协程延迟任务", Toast.LENGTH_SHORT).show()
        }
    }
}

​依赖​

Kotlin 复制代码
implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.8.0"

五、总结建议​

​场景​ ​推荐方案​ ​理由​
简单 UI 更新 Handler(Looper.getMainLooper()) 代码简洁
复杂生命周期任务 LifecycleAwareHandler 自动清理消息,避免泄漏
新项目/异步任务 ​协程​ 语法简洁、安全,官方推荐
定时循环任务 Handler#postDelayed+ 自递归 精确控制间隔(需注意泄漏)