在 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 + 自递归 |
精确控制间隔(需注意泄漏) |