【问题标题】:ViewModel Instantiation Causes Infinite LoopViewModel 实例化导致无限循环
【发布时间】:2019-08-29 03:48:36
【问题描述】:

我正在使用我之前使用过几次的模式来实例化ViewModel 对象。在这种情况下,数据以字符串形式保存在SharedPreferences 中。我只需要读取该字符串,将其解析为正确的对象,然后将该对象作为值分配给我的视图模型。

但是当我做分配时,我创建了一个无限循环。

class UserDataViewModel(private val prefs: SharedPreferences): ViewModel() {

    val userData: MutableLiveData<UserData> by lazy {
        MutableLiveData<UserData>().also {
            val userDataString = prefs.getString(Authenticator.USER_DATA, "")
            val ud = Gson().fromJson(userDataString, UserData::class.java)
            userData.value = ud // infinite loop is here
        }
    }

    fun getUserData(): LiveData<UserData> {
        return userData
    }
}

这是在片段的onCreateView() 中保留对ViewModel 的引用:

userDataViewModel = activity?.run {
            ViewModelProviders
                 .of(this, UserDataViewModelFactory(prefs))
                 .get(UserDataViewModel::class.java)
            } ?: throw Exception("Invalid Activity")

userDataViewModel
    .getUserData()
    .observe(this, Observer {
        binding.userData = userDataViewModel.userData.value
    })

FWIW,在片段中,我在 getUserData()binding.userData... 上都有断点。最后一个被击中的断点是getUserData()

我看不到循环的创建位置。感谢您的帮助。

【问题讨论】:

    标签: android mvvm android-viewmodel


    【解决方案1】:

    userData 字段仅在by lazy {} 块返回时才被初始化。您正在从 by lazy {} 块内访问 userData 字段,这就是创建循环的原因 - 内部访问看到它尚未完成初始化,因此它再次运行该块......一次又一次。

    相反,您可以使用it 而不是userData 来访问您在also 块中修改的MutableLiveData,从而打破循环:

    val userData: MutableLiveData<UserData> by lazy {
        MutableLiveData<UserData>().also {
            val userDataString = prefs.getString(Authenticator.USER_DATA, "")
            val ud = Gson().fromJson(userDataString, UserData::class.java)
            it.value = ud
        }
    }
    

    【讨论】:

    • 非常有意义。谢谢!
    • 是的也解决了我的同源问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-21
    • 2011-03-24
    • 2020-08-27
    • 2021-05-07
    • 2012-08-24
    相关资源
    最近更新 更多