android 之 Kotlin中Handler的使用

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

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. ​​延迟执行任务​
// 延迟 3 秒显示 Toast
mainHandler.postDelayed({
    Toast.makeText(this, "延迟 3 秒执行", Toast.LENGTH_SHORT).show()
}, 3000)

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

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

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

​方案 1:静态内部类 + 弱引用​
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​
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 开发中,协程更简洁且避免内存泄漏:

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()
        }
    }
}

​依赖​

implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.8.0"

五、总结建议​

​场景​

​推荐方案​

​理由​

简单 UI 更新

Handler(Looper.getMainLooper())

代码简洁

复杂生命周期任务

LifecycleAwareHandler

自动清理消息,避免泄漏

新项目/异步任务

​协程​

语法简洁、安全,官方推荐

定时循环任务

Handler#postDelayed+ 自递归

精确控制间隔(需注意泄漏)

Kotlin 中,Handler 通常用于 Android 开发中的线程间通信(如主线程与后台线程的交互),还可用于延迟任务调度,以下是几种常见的使用方法: ### 绑定主线程 Looper 进行线程间通信 在 Android Kotlin 开发中,可通过绑定主线程 Looper 实现后台线程更新 UI。示例代码如下: ```kotlin import android.os.Bundle import android.os.Handler import android.os.Looper import androidx.appcompat.app.AppCompatActivity import com.example.test.databinding.ActivityMainBinding 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" } } } } ``` 在上述代码中,`mainHandler` 绑定了主线程的 Looper,在后台线程执行完耗时任务后,使用 `mainHandler.post` 方法将更新 UI 的操作切换到主线程执行 [^2]。 ### 使用 static 内部类 + WeakReference 弱引用的方式 为避免内存泄漏,可采用 static 内部类 + WeakReference 弱引用的方式使用 Handler。示例代码如下: ```kotlin import android.os.Bundle import android.os.Handler import android.os.Looper import android.os.Message import androidx.appcompat.app.AppCompatActivity import java.lang.ref.WeakReference class HandlerActivity : AppCompatActivity() { companion object { const val WHAT_HINT_TEXT = 1000 // MSG_WHAT } private val mOutPut = "我输出了" // 成员变量 private val weakHandler by lazy { WeakReferenceHandler(this) } // static + 弱引用 class WeakReferenceHandler(obj: HandlerActivity) : Handler(Looper.getMainLooper()) { private val mRef: WeakReference<HandlerActivity> = WeakReference(obj) override fun handleMessage(msg: Message) { mRef.get()?.run { when (msg.what) { WHAT_HINT_TEXT -> println(mOutPut) // 可以直接访问 Activity 中的变量 } } } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) weakHandler.sendEmptyMessageDelayed(WHAT_HINT_TEXT, 5000) } override fun onDestroy() { // 退出页面时,置空所有的 Message weakHandler.removeCallbacksAndMessages(null) super.onDestroy() } } ``` 在上述代码中,`WeakReferenceHandler` 是一个静态内部类,使用 `WeakReference` 弱引用持有 `HandlerActivity` 的引用,避免了内存泄漏。在 `onDestroy` 方法中,调用 `removeCallbacksAndMessages` 方法移除所有未处理的消息 [^3]。 ### 使用匿名函数处理消息 通过匿名函数的方式处理消息,示例代码如下: ```kotlin import android.os.Handler import android.util.Log val handler2: Handler = Handler { when (it.what) { 9999 -> { try { var t = it.data.get("data") Log.d("TAG", "t=$t") } catch (ex: Throwable) { ex.printStackTrace() } } else -> { Log.d("TAG", "handler else") } } false } ``` 在上述代码中,使用匿名函数处理消息,根据 `msg.what` 的值进行不同的处理 [^4]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值