Anko doAsync与uiThread废弃后的Android异步替代方案咨询
Anko
doAsync/uiThread 废弃替代方案 你原来的代码逻辑非常典型:IO线程跑数据库查询,查完切主线程更新列表,目前有两个非常成熟的零成本替换方案,优先选第一个就行。
方案1:Kotlin协程(官方首推,替换成本最低)
这是目前Android官方推荐的标准异步实现,和你之前的写法逻辑完全对齐,还自带生命周期安全,不会出现内存泄漏、销毁后更新UI的崩溃问题。
- 先替换依赖,把原来的anko依赖删掉,加协程依赖:
dependencies { implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3" }
- 直接替换原有业务代码,几乎是一一对应:
// 导包不要错 import androidx.lifecycle.lifecycleScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext private fun getStores() { // 用Activity自带的lifecycleScope启动协程,页面销毁时任务自动取消 lifecycleScope.launch { // Dispatchers.IO对应后台IO线程,执行数据库查询这类耗时操作 val stores = withContext(Dispatchers.IO) { StoreAplication.database.storeDao().getAllStores() } // 协程默认会自动切回主线程,直接更新UI即可,对应原来的uiThread块 mAdapter.setStores(stores) } }
这个方案的优势:
- 不用自己管理线程切换、线程池复用
- 不用写额外的生命周期解绑逻辑,不会内存泄漏
- 后续如果要做串行/并行的多任务处理,协程写起来比原来的Anko更简洁
方案2:原生线程+Handler(不想引入协程时临时用)
如果项目暂时不方便加协程依赖,可以直接用Android原生API实现完全一样的逻辑,缺点是要自己处理生命周期,避免页面销毁后任务还在跑。
import android.os.Handler import android.os.Looper import java.util.concurrent.Executors // 可以定义成单例的公共线程池,不要每次点击都新建线程 private val ioExecutor = Executors.newFixedThreadPool(2) private val mainHandler = Handler(Looper.getMainLooper()) private fun getStores() { ioExecutor.execute { // 后台线程执行耗时查询,对应原来doAsync的代码块 val stores = StoreAplication.database.storeDao().getAllStores() // 切主线程更新UI,对应原来uiThread的代码块 mainHandler.post { // 这里要注意加判断,Activity已经销毁的话就不要执行更新逻辑了,避免崩溃 if (!isFinishing && !isDestroyed) { mAdapter.setStores(stores) } } } }
避坑提醒:不要用同样已经废弃的
AsyncTask做替换,这个API已经被官方从Android 11开始标记废弃,存在已知的内存泄漏问题,没有使用价值。
内容的提问来源于stack exchange,提问作者SantiGuido
相关产品推荐
相关产品推荐

