Kotlin新手求助:Android中Activity为空时避免调用回调的方案
刚接触Kotlin碰到这个需求太常见啦——毕竟谁都不想在Activity已经销毁的时候还去更新UI,轻则白忙活,重则直接崩给你看。我给你整理了几个实用的方案,从简单到优雅都有,你可以根据自己的项目情况选:
这个方法最直接,把Activity包装成WeakReference,在回调执行前先检查这个引用是否还持有有效的Activity实例,只有存在有效实例时才更新UI。
在MainActivity里调用的时候这么写:
// 把当前Activity包装成弱引用 val activityRef = WeakReference(this) DataManager.performWork(callback = { param1, param2 -> // 先取出Activity实例,判空后再执行UI操作 val currentActivity = activityRef.get() currentActivity?.run { // 在这里放心更新UI tv_result.text = param1.toString() } })
优点是不用改DataManager的原有代码,直接在调用层处理,适合快速解决问题;缺点是每次都要手动写判空逻辑,有点繁琐。
如果你的项目用了Jetpack组件,用Lifecycle来感知Activity的生命周期状态会更专业,能自动在Activity不可用时跳过回调,还能避免内存泄漏。
首先给DataManager加一个带LifecycleOwner的重载方法:
fun performWork(lifecycleOwner: LifecycleOwner, callback: ((param1: T, param2) -> Unit)?) { // 先判断Activity是否处于活跃状态(STARTED或RESUMED) if (!lifecycleOwner.lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)) { callback?.let { return } // 直接返回,不执行回调 } // 这里写你的异步处理逻辑... // 异步操作完成后,再次检查生命周期状态 if (lifecycleOwner.lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)) { callback?.invoke(param1, param2) } // 可选:添加生命周期观察者,在Activity销毁时取消异步操作 lifecycleOwner.lifecycle.addObserver(object : DefaultLifecycleObserver { override fun onDestroy(owner: LifecycleOwner) { // 比如取消网络请求、停止耗时任务等 owner.lifecycle.removeObserver(this) } }) }
然后在MainActivity里调用就很简洁了:
DataManager.performWork(this) { param1, param2 -> // 这里更新UI,不用担心Activity已销毁 tv_result.text = param1.toString() }
这个方案完全贴合Android的生命周期规范,能从根源上避免无效的UI操作,推荐在现代Android项目中使用。
如果你的项目已经在用协程处理异步逻辑,那直接用Activity的lifecycleScope就最省心了——协程会自动在Activity销毁时取消,后续的UI更新代码自然不会执行。
先把DataManager的方法改成挂起函数:
suspend fun performWork(): Pair<T, Param2Type> { // 异步处理逻辑,比如切换到IO线程执行耗时操作 return withContext(Dispatchers.IO) { // 执行数据操作,返回结果 Pair(processedParam1, processedParam2) } }
然后在MainActivity里调用:
lifecycleScope.launch { // 这个协程会在Activity销毁时自动取消 val (param1, param2) = DataManager.performWork() // 只有Activity活跃时才会执行到这里 tv_result.text = param1.toString() }
这个方案完全不用手动处理回调的有效性,协程框架帮你搞定一切,代码也最简洁,是目前Android异步开发的主流方式。
内容的提问来源于stack exchange,提问作者user2434385

