我从不进入我的 ViewModel 中的 LiveDataScope
I never enter inside the LiveDataScope inside my ViewModel
我开发了2个登录功能。
当我使用 ViewModel 范围时,第一个“loginOne”有效。
另一个在我使用 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
电话看起来很可疑。
When using LiveData, you might need to calculate values asynchronously. For example, you might want to retrieve a user's preferences and serve them to your UI. In these cases, you can use the liveData builder function to call a suspend function, serving the result as a LiveData object.
Each emit() call suspends the execution of the block until the LiveData value is set on the main thread.
In the example below, loadUser() is a suspend function declared elsewhere. Use the liveData builder function to call loadUser() asynchronously, and then use emit() to emit the result:
val user: LiveData<User> = liveData {
val data = database.loadUser() // loadUser is a suspend function.
emit(data)
}
编辑: MutableLiveData
用于 user
变量 - 解决了问题。
来自文档:
The liveData building block serves as a structured concurrency
primitive between coroutines and LiveData. The code block starts
executing when LiveData becomes active and is automatically canceled
after a configurable timeout when the LiveData becomes inactive.
因此,在您的情况下,当您从片段中观察时,'user' liveData 已经激活。因为您在观察到 liveData 后调用了 loginTwo(),所以不会再触发 emit 函数。在观察 liveData 之前尝试调用 loginTwo() 以从 liveData ktx 获取发射值。
我开发了2个登录功能。
当我使用 ViewModel 范围时,第一个“loginOne”有效。
另一个在我使用 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
电话看起来很可疑。
When using LiveData, you might need to calculate values asynchronously. For example, you might want to retrieve a user's preferences and serve them to your UI. In these cases, you can use the liveData builder function to call a suspend function, serving the result as a LiveData object.
Each emit() call suspends the execution of the block until the LiveData value is set on the main thread.
In the example below, loadUser() is a suspend function declared elsewhere. Use the liveData builder function to call loadUser() asynchronously, and then use emit() to emit the result:
val user: LiveData<User> = liveData {
val data = database.loadUser() // loadUser is a suspend function.
emit(data)
}
编辑: MutableLiveData
用于 user
变量 - 解决了问题。
来自文档:
The liveData building block serves as a structured concurrency primitive between coroutines and LiveData. The code block starts executing when LiveData becomes active and is automatically canceled after a configurable timeout when the LiveData becomes inactive.
因此,在您的情况下,当您从片段中观察时,'user' liveData 已经激活。因为您在观察到 liveData 后调用了 loginTwo(),所以不会再触发 emit 函数。在观察 liveData 之前尝试调用 loginTwo() 以从 liveData ktx 获取发射值。