我已经开发了2个用于登录的功能。
第一个“ [loginOne”在使用ViewModel范围时有效。
当我使用LiveData范围时,另一个不起作用。
你有个主意吗?我想使“ loginTwo”工作。
API
interface LoginAPI {
@POST("login")
suspend fun getUser(@Body loginRequest: LoginRequest): User
}
存储库
class LoginRepository(private val loginAPI: LoginAPI) {
suspend fun getUser(loginRequest: LoginRequest) = loginAPI.getUser(loginRequest)
}
ViewModel
class LoginViewModel(private val loginRepository: LoginRepository) : ViewModel() {
private var user: LiveData<User>? = null
fun loginOne(username: String, password: String) {
viewModelScope.launch {
// i can enter here and get the user :)
val user = loginRepository.getUser(LoginRequest(username, password))
user
}
}
fun loginTwo(username: String, password: String) {
user = liveData(Dispatchers.IO) {
// i never enter inside.. why ?
val user = loginRepository.getUser(LoginRequest(username, password))
emit(user)
}
}
fun getUser(): LiveData<User>? = user
}
Fragment,我的viewModel注入了Koin
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
loginViewModel.getUser()?.observe(this, Observer { user ->
Log.d(LoginFragment::class.java.name, "User : $user ")
})
loginViewModel.loginOne("user","pcw123")
loginViewModel.loginTwo("user","pcw123")
}
请确保您以正确的方式创建了Scope
。另外,您正在使用适当的Dispatchers
来获得所需的结果。
您还可以在需要postValue
时检查呼叫是否正在执行。检查Job
是否仍然有效。
检查此thing。您的emmit
通话看起来很可疑。
使用LiveData时,您可能需要异步计算值。例如,您可能想检索用户的首选项并将其提供给您的UI。在这些情况下,您可以使用liveData构建器函数调用暂停函数,将结果用作LiveData对象。
每个emit()调用将中止块的执行,直到在主线程上设置了LiveData值为止。
在下面的示例中,loadUser()是在其他地方声明的暂停函数。使用liveData构建器函数异步调用loadUser(),然后使用emit()发出结果:
val user: LiveData<User> = liveData {
val data = database.loadUser() // loadUser is a suspend function.
emit(data)
}