我有一个问题,我认为可以追溯到ViewModel
范围界定。我在同一活动下的同一导航图中有两个片段。第一个片段LoginFragment
实例化UserDataViewModel
并将其某些数据填充到名为UserData
]的对象中
第二个片段,TodayFragment
应该使用UserDataViewModel
,并使用已经填充的属性来做进一步的工作。但是,在TodayFragment
尝试访问UserData
对象时,该对象为空。要强调的是,UserDataViewModel
仍然具有相同的内存地址,但是问题在于它丢失了对其数据值的引用。
我已对此进行了简化,以便数据仅从SharedPreferences
中提取一个字符串并使用GSON对其进行解析。
LoginFragment
:private lateinit var userDataViewModel: UserDataViewModel override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) MyApplication.appComponent?.inject(this) prefs = PreferenceManager.getDefaultSharedPreferences(context) userDataViewModel = activity?.run { ViewModelProviders .of(this, UserDataViewModelFactory(prefs, dataFetcherService)) .get(UserDataViewModel::class.java) } ?: throw Exception("Invalid Activity") userDataViewModel.getUserData() }
TodayFragment
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) prefs = PreferenceManager.getDefaultSharedPreferences(activity) userDataViewModel = activity?.run { ViewModelProviders .of(this, UserDataViewModelFactory(prefs, dataFetcherService)) .get(UserDataViewModel::class.java) } ?: throw Exception("Invalid Activity") } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) userDataViewModel .getUserData() .observe(this, Observer { clubId = it.club_id // <-- this is where it crashes since 'it' is null }) }
UserDataViewModel.kt
class UserDataViewModel( prefs: SharedPreferences, dataFetcherService: DataFetcherService) : ViewModel() { private val useCase = UserDataUseCase(prefs, dataFetcherService) val userData: MutableLiveData<UserData> by lazy { MutableLiveData<UserData>().apply { loadUserData() } } fun getUserData(): LiveData<UserData> { return userData } private fun loadUserData() { viewModelScope.launch { withContext(Dispatchers.IO) { try { return@withContext useCase.loadUserData(USER_UNKNOWN) } catch (t: Throwable) { return@withContext null } } ?.let { userData.postValue(it) } } } }
很奇怪的地方是视图模型的
getUserData()
方法中。当我在这些行上设置断点时:
return userData
MutableLiveData<UserData>().apply { loadUserData() }
return@withContext useCase.loadUserData(USER_UNKNOWN)
这些断点都击中LoginFragment。但是,当它进入TodayFragment时,它会在视图模型中命中return userData
,然后立即跳回到TodayFragment内部的观察者,并且视图模型内部的值具有空指针异常。
我认为在实例化视图模型本身的范围内是有意义的,但是为什么inside
值却为null?出于调试目的,我正在对用例和存储库中的响应进行硬编码,以确保在视图模型中填充了一个值。
LoginFragment的屏幕截图
TodayFragment的屏幕截图(扩展了AbstractWorkoutFragment)
请注意mData
现在如何为空,但ViewModel相同。我有一个问题,我认为可以追溯到ViewModel范围。我在同一活动下的同一导航图中有两个片段。第一个片段LoginLogin实例化了一个...
在包含两个片段的活动中实例化userDataViewModel。在活动中填充用户数据,并将其传递给子片段。