Kotlin中如何等待跨类初始化的lateinit变量完成赋值?
问题:异步初始化变量导致后续逻辑执行时机错误
在ChatActivity中声明了lateinit var currentUser: User,在onCreate里调用getUserDetails()触发Firebase异步初始化,但后续判断currentUser.id的代码会因为异步操作未完成,导致currentUser未初始化而报错,需要让依赖该变量的后续逻辑等待初始化完成后再执行。
方案1:将后续逻辑移到回调方法内(最简单直接)
既然异步操作的结果会在userDetailsSuccess回调中返回,直接把需要使用currentUser的代码放到这个方法里,确保只有变量初始化完成后才执行相关逻辑:
修改userDetailsSuccess方法:
fun userDetailsSuccess(user: User) { Log.e("user", "success") hideProgressDialog() currentUser = user // 把原本在onCreate里的判断逻辑移到这里 if(currentUser.id == mProductDetails.user_id) { isSeller = true // 这里还可以添加其他依赖currentUser的逻辑,比如更新UI等 } }
同时,onCreate里移除那部分提前执行的逻辑:
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_product_chat) setupActionBar() getUserDetails() // 移除原本的if判断逻辑,放到回调里执行 }
方案2:用协程封装异步操作(更优雅的Kotlin方式)
如果不想把逻辑都堆在回调里,可以用Kotlin协程将Firebase的异步回调转为挂起函数,让onCreate中的流程按顺序执行:
第一步:在FireStoreClass中封装挂起函数
// FireStoreClass.kt suspend fun getUserDetailsSuspend(): User { return suspendCoroutine { continuation -> // 这里实现原本的Firebase查询逻辑 FirebaseFirestore.getInstance() .collection(Constants.USERS) .document(getCurrentUserID()) .get() .addOnSuccessListener { document -> val user = document.toObject(User::class.java)!! continuation.resume(user) } .addOnFailureListener { e -> continuation.resumeWithException(e) } } }
第二步:在Activity的协程作用域中调用
// ChatActivity.kt private lateinit var currentUser: User override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_product_chat) setupActionBar() lifecycleScope.launch { // 用lifecycleScope绑定协程与Activity生命周期 showProgressDialog(resources.getString(R.string.please_wait)) try { currentUser = FireStoreClass().getUserDetailsSuspend() // 初始化完成后执行后续逻辑 if(currentUser.id == mProductDetails.user_id) { isSeller = true } } catch (e: Exception) { // 处理异常,比如打印日志或显示错误提示 Log.e("UserDetails", "获取用户信息失败", e) } finally { hideProgressDialog() } } }
方案3:使用LiveData观察变量状态(适合MVVM架构)
如果项目采用MVVM架构,可以用LiveData来观察currentUser的变化,当变量初始化完成后自动触发逻辑:
第一步:在ViewModel中定义LiveData
class ChatViewModel : ViewModel() { private val _currentUser = MutableLiveData<User?>() val currentUser: LiveData<User?> = _currentUser fun getUserDetails() { FireStoreClass().getUserDetails(object : FireStoreCallback { override fun onSuccess(user: User) { _currentUser.postValue(user) } override fun onFailure(e: Exception) { // 处理查询失败的情况,比如记录日志 } }) } }
第二步:在Activity中观察LiveData
// ChatActivity.kt private lateinit var viewModel: ChatViewModel override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_product_chat) setupActionBar() viewModel = ViewModelProvider(this)[ChatViewModel::class.java] viewModel.currentUser.observe(this) { user -> user?.let { currentUser = it // 初始化完成后执行逻辑 if(currentUser.id == mProductDetails.user_id) { isSeller = true } } } viewModel.getUserDetails() }
内容的提问来源于stack exchange,提问作者Malhar
相关产品推荐
相关产品推荐

