Kotlin中如何将LiveData结果作为函数参数传递(ViewModel场景)
问题根因
- 你直接调用
_token.value时,Preference Store的Flow还没完成首次数据发射,asLiveData()转换后的LiveData初始值默认是null,所以你拿到的是空值。 - 额外隐患:
appPreferenceStorage.accessToken.asLiveData()返回的是只读的LiveData类型,你强转成MutableLiveData属于不安全操作,后续如果尝试setValue/postValue会直接抛出类型异常。
解决方案
方案1:直接使用Flow(推荐)
LiveData本身是设计给View层观察生命周期感知数据的,你在ViewModel内部使用完全不需要把Flow转成LiveData,直接操作Flow更适配协程场景:
- 首先修改token的声明,取消LiveData转换:
// 直接保留Flow类型即可 val tokenFlow: Flow<String> = appPreferenceStorage.accessToken
- 修改updateFirstName方法,等待Flow发射有效值后再执行请求:
fun updateFirstName(view: View) { viewModelScope.launch { // first()是挂起函数,会等待Flow发射第一个值后再往下执行 // 如果需要过滤空值可以写成 tokenFlow.filterNotNull().first() val token = tokenFlow.first() profileRepository.updateFirstName(token, "Bob", object : ProfileListener { override fun onSuccess(response: String?) { Timber.d(response) } override fun onFailure(localizedMessage: String?) { Timber.e(localizedMessage) } }) } }
方案2:坚持使用LiveData的情况
如果确实需要保留LiveData的声明,就通过观察者拿到有效值后再执行操作,注意及时移除观察者避免内存泄漏:
fun updateFirstName(view: View) { token.observeForever(object : Observer<String> { override fun onChanged(value: String?) { // 过滤空值,等拿到有效token再执行 value?: return viewModelScope.launch { profileRepository.updateFirstName(value, "Bob", object : ProfileListener { override fun onSuccess(response: String?) { Timber.d(response) } override fun onFailure(localizedMessage: String?) { Timber.e(localizedMessage) } }) } // 执行完请求立刻移除观察者,避免后续token更新重复触发逻辑 token.removeObserver(this) } }) }
内容的提问来源于stack exchange,提问作者Dr4ke the b4dass
相关产品推荐
相关产品推荐

