使用Firebase Realtime Database时启动新线程的最佳实践是什么?
优化方案
直接创建Thread存在的问题
- 线程的创建、销毁开销很高,若Firebase数据频繁更新,会产生大量临时线程,占用系统资源,严重时会触发OOM
- 无统一的线程管理机制,无法控制并发数量,任务调度混乱
- 临时线程没有统一的异常捕获机制,运行时崩溃会直接触发应用闪退
具体改造步骤
1. 配置全局复用线程池
创建全局单例的线程池实例,整个应用共用同一套线程资源,避免重复创建线程池浪费资源:
import java.util.concurrent.Executor import java.util.concurrent.Executors object AppExecutors { // 定长线程池核心数设为CPU核心数的2倍,适配序列化/反序列化这类轻量CPU任务+普通IO任务 val diskIOExecutor: Executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 2) }
你也可以根据自身业务需求,单独配置网络IO、主线程调度等其他场景的Executor。
2. 替换ViewModel中的线程调用逻辑
把原来手动创建Thread的逻辑替换为向线程池提交Runnable任务即可:
private val uid = Firebase.auth.currentUser!!.uid private val USERS_REF: DatabaseReference = FirebaseDatabase.getInstance().getReference("/users/$uid") private val liveData: FirebaseQueryLiveData = FirebaseQueryLiveData(USERS_REF) private val usersLiveData: MediatorLiveData<Users> = MediatorLiveData() init { // Kotlin中ViewModel的初始化逻辑要放在init块,实例创建时会自动执行,不要声明和类同名的函数 usersLiveData.addSource(liveData) { dataSnapshot -> if (dataSnapshot != null) { // 向复用线程池提交反序列化任务 AppExecutors.diskIOExecutor.execute { usersLiveData.postValue(dataSnapshot.getValue(Users::class.java)) } } else { usersLiveData.value = null } } }
可选进阶优化(Kotlin协程)
如果你的项目已经接入Kotlin协程,可以用ViewModel自带的viewModelScope实现更安全的后台任务调度,无需手动管理线程池,ViewModel销毁时会自动取消所有未完成的任务,避免内存泄漏:
init { usersLiveData.addSource(liveData) { dataSnapshot -> if (dataSnapshot != null) { // 自动绑定ViewModel生命周期,IO线程执行反序列化 viewModelScope.launch(Dispatchers.IO) { val users = dataSnapshot.getValue(Users::class.java) usersLiveData.postValue(users) } } else { usersLiveData.value = null } } }
内容的提问来源于stack exchange,提问作者Tom Darious
相关产品推荐
相关产品推荐

