You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 12:55:34