我想在我最近的應用程式中實作Clean Architecture。但我面臨著在useCase中處理錯誤的一些問題。我無法處理從Usecase類中拋出的例外,盡管其他基于庫的例外被成功地處理了。這意味著,當Firebase拋出任何例外時,它被成功地處理了,并在Toast中顯示了例外文本。但是當我從Usecase類中拋出任何例外時,比如
。請填寫兩個欄位
或者
請提供電子郵件
或者
請提供密碼
然后應用程式崩潰了。那么,我如何處理用例類的例外并在Toast中顯示文本呢?
以下是我嘗試的代碼。
FirebaseAuthRepository.kt
interface FirebaseAuthRepository {
suspend fun register(email: String, password: String): Flow<User>
}
FirebaseAuthRepositoryImpl.kt
class FirebaseAuthRepositoryImpl @Inject constructor(
private val firebaseAuthDataSource: FirebaseAuthDataSource。
private val firebaseAuthMapper: 私有值 FirebaseAuthMapper:FirebaseAuthMapper
) : FirebaseAuthRepository {
override suspend fun register(email: String, password: String): Flow<User> {
回傳flow {
emit(firebaseAuthDataSource.register(email, password))
}.map {
firebaseAuthMapper.toUser(it)
}
}
}
FirebaseAuthDataSource.kt
class FirebaseAuthDataSource @Inject constructor(private val firebaseAuth: FirebaseAuth) {
suspend fun register(email: String, password: String): FirebaseUser? {
val authResult: AuthResult = firebaseAuth.createUserWithEmailAndPassword(email, password).await()
回傳 authResult.user
}
}
RegisterUseCase.kt
class RegisterUseCase @Inject constructor(
private val firebaseAuthRepository: FirebaseAuthRepository
) {
suspend fun execute(email: String, password: String): Flow<User> {
if (email.trim().isEmpty() && password.trim().isEmpty() ) {
throw Exception("Please fill both field")
} else {
if (email.trim().isEmpty()) throw Exception("Please give email")
if (password.trim().isEmpty()) throw Exception("Please give password")
}
return firebaseAuthRepository.register(email, password)
}
}
LoginViewModel.kt
@HiltViewModel
class LoginViewModel @Inject constructor(
private val registerUseCase: RegisterUseCase
) : BaseViewModel() {
val register: MutableStateFlow<資源<用戶>> = MutableStateFlow(Loading(true))
fun register(email: String, password: String) {
viewModelScope.launch {
loginUseCase.execute(email, password)
.flowOn(Dispatchers.IO)
.onStart { }
.onCompletion { register.value = Loading(false) }
.catch { register.value = Error(it) }
.collectLatest { register.value = Success(it) }
}
}
}
Resource.kt
密封類Resource<out T> {
資料類 Loading(val isLoading: Boolean) : Resource<Nothing> ()
資料類 Success<T>(val item: T) : Resource<T>()
資料類 Error(val throwable: Throwable) : Resource<Nothing>()
}
RegistrationFragment.kt
@AndroidEntryPoint
class RegistrationFragment : BaseFragment<FragmentRegisterBinding>() {
private val viewModel: 注冊ViewModel by viewModels()
override fun getViewBinding(
inflater: LayoutInflater,
容器。ViewGroup?
): FragmentRegisterBinding {
return FragmentRegisterBinding.inflate(inflater, container, false)
}
override fun configureViews() {
binding.registerButton.setOnClickListener {
viewModel.register(
binding?.mailEditText?.value() ? : "",
binding?.passwordEditText?.value() ?: ""
)
}
}
override fun bindWithViewModel() {
lifecycleScope.launch {
viewModel.registration.collectLatest {
when(it) {
is Loading -> {
if (it.isLoading) {
} else {
}
}
是成功 -> {
findNavController().navigate(R.id.home_fragment)
}
是錯誤 -> {
requireContext().toast(it.throwable.message ?: "" )
}
}
}
}
}
}
uj5u.com熱心網友回復:
像下面這樣使用一個CoroutineExceptionHandler處理程式(你可以把它放到BaseViewModel中)
val handler = CoroutineExceptionHandler { _, exception ->
運行 {
toast.value = exception.message
exception.printStackTrace()
Log.e(TAG, "Caught $exception")
}
}
然后在你的viewModel中添加handler,其中viewModelScope. launch
fun register(email: String, password: String) {
viewModelScope.launch(handler) {
loginUseCase.execute(email, password)
.flowOn(Dispatchers.IO)
.onStart { }
.onCompletion { register.value = Loading(false) }
.catch { register.value = Error(it) }
.collectLatest { register.value = Success(it) }
}
}
uj5u.com熱心網友回復:
最后我解決了這個問題。非常感謝@Rifan vai的回答。這里的代碼,我試了一下。
BaseViewmodel.kt
抽象類BaseViewModel : ViewModel() {
fun handleException(action: (Throwable)->Unit)。CoroutineExceptionHandler {
return CoroutineExceptionHandler { _, exception ->
動作(exception)
}
}
}
LoginViewModel.kt
@HiltViewModel
class LoginViewModel @Inject constructor(
private val loginUseCase: LoginUseCase
) : BaseViewModel() {
val login: MutableStateFlow<資源<用戶>> = MutableStateFlow(Loading(true))
fun login(email: String, password: String) {
viewModelScope.launch(handleException { login.value = Error(it) }) {
loginUseCase.execute(email, password)
.flowOn(Dispatchers.IO)
.onCompletion { login.value = Loading(false) }
.collectLatest { login.value = Success(it) }
}
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/320020.html
標籤:
