我是 Android 開發的新手,并試圖了解協程和LiveData
各種示例專案。我目前已經設定了一個函式來在用戶輸入用戶名和密碼時呼叫我的 api。但是,在按下 1 個按鈕后,該應用程式似乎卡住了,我無法進行另一個 api 呼叫,就好像它卡在一個待處理的行程上一樣。
這是我第一個用大量想法制作的安卓應用程式,所以請讓我知道我在哪里犯了錯誤!
活動:
binding.bLogin.setOnClickListener {
val username = binding.etUsername.text.toString()
val password = binding.etPassword.text.toString()
viewModel.userClicked(username, password).observe(this, Observer {
it?.let { resource ->
when (resource.status) {
Status.SUCCESS -> {
print(resource.data)
}
Status.ERROR -> {
print(resource.message)
}
Status.LOADING -> {
// loader stuff
}
}
}
})
}
視圖模型:
fun userClicked(username: String, password: String) = liveData(dispatcherIO) {
viewModelScope.launch {
emit(Resource.loading(data = null))
try {
userRepository.login(username, password).apply {
emit(Resource.success(null))
}
} catch (exception: Exception) {
emit(Resource.error(exception.message ?: "Error Occurred!", data = null))
}
}
}
存盤庫:
@WorkerThread
suspend fun login(
username: String,
password: String
): Flow<Resource<String?>> {
return flow {
emit(Resource.loading(null))
api.login(LoginRequest(username, password)).apply {
this.onSuccessSuspend {
data?.let {
prefs.apiToken = it.key
emit(Resource.success(null))
}
}
}.onErrorSuspend {
emit(Resource.error(message(), null))
}.onExceptionSuspend {
emit(Resource.error(message(), null))
}
}.flowOn(dispatcherIO)
}
介面:
suspend fun login(@Body request: LoginRequest): ApiResponse<Auth>
uj5u.com熱心網友回復:
您不需要在liveData
構建器中啟動協程,它已經是suspend
這樣您可以suspend
在那里呼叫函式:
fun userClicked(username: String, password: String) = liveData(dispatcherIO) {
emit(Resource.loading(data = null))
try {
userRepository.login(username, password).apply {
emit(Resource.success(null))
}
} catch (exception: Exception) {
emit(Resource.error(exception.message ?: "Error Occurred!", data = null))
}
}
如果你想與你一起使用LiveDate
,你可以使用函式Flow
轉換Flow
為LiveData
物件:asLiveData
fun userClicked(username: String, password: String): LiveData<Resource<String?>> {
return userRepository.login(username, password).asLiveData()
}
但我不建議在專案中混合LiveData
和Flow
流式傳輸。我建議只使用Flow
.
僅使用Flow
:
// In ViewModel:
fun userClicked(username: String, password: String): Flow<Resource<String?>> {
return userRepository.login(username, password)
}
// Activity
binding.bLogin.setOnClickListener {
val username = binding.etUsername.text.toString()
val password = binding.etPassword.text.toString()
lifecycleScope.launch {
viewModel.userClicked(username, password).collect { resource ->
when (resource.status) {
Status.SUCCESS -> {
print(resource.data)
}
Status.ERROR -> {
print(resource.message)
}
Status.LOADING -> {
// loader stuff
}
}
}
}
}
從 中的函式中洗掉suspend
關鍵字。login
Repository
lifecycleScope
檔案。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/477367.html
標籤:安卓 科特林 kotlin 协程 安卓实时数据 科特林流
上一篇:ReactNative:文本onPress在android上不起作用
下一篇:將(newIntent(Intent.ACTION_SENDTO)).setData(Uri.parse("mailto:")傳遞給intent.setSelector()在選擇器