Skip to content

Commit 37de128

Browse files
author
Lucas Sales
committed
Adding view model tag extensions
1 parent 567e574 commit 37de128

File tree

3 files changed

+73
-20
lines changed

3 files changed

+73
-20
lines changed
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// Package set to androidx.lifecycle so we can have access to package private methods
2+
3+
package androidx.lifecycle
4+
5+
import com.monstarlab.arch.extensions.UseCaseResult
6+
import com.monstarlab.arch.extensions.onError
7+
import com.monstarlab.core.sharedui.errorhandling.ViewError
8+
import com.monstarlab.core.sharedui.errorhandling.mapToViewError
9+
import kotlinx.coroutines.flow.*
10+
import kotlinx.coroutines.launch
11+
12+
private const val ERROR_FLOW_KEY = "androidx.lifecycle.ErrorFlow"
13+
private const val LOADING_FLOW_KEY = "androidx.lifecycle.LoadingFlow"
14+
15+
fun ViewModel.sendViewError(viewError: ViewError) {
16+
viewModelScope.launch {
17+
getErrorMutableSharedFlow().emit(viewError)
18+
}
19+
}
20+
21+
suspend fun ViewModel.emitViewError(viewError: ViewError) {
22+
getErrorMutableSharedFlow().emit(viewError)
23+
}
24+
25+
val ViewModel.viewErrorFlow: SharedFlow<ViewError>
26+
get() {
27+
return getErrorMutableSharedFlow()
28+
}
29+
30+
val ViewModel.loadingFlow: StateFlow<Boolean>
31+
get() {
32+
return getLoadingMutableStateFlow()
33+
}
34+
35+
36+
private fun ViewModel.getLoadingMutableStateFlow(): MutableStateFlow<Boolean> {
37+
val flow: MutableStateFlow<Boolean>? = getTag(LOADING_FLOW_KEY)
38+
return flow ?: setTagIfAbsent(ERROR_FLOW_KEY, MutableStateFlow(false))
39+
}
40+
41+
private fun ViewModel.getErrorMutableSharedFlow(): MutableSharedFlow<ViewError> {
42+
val flow: MutableSharedFlow<ViewError>? = getTag(ERROR_FLOW_KEY)
43+
return flow ?: setTagIfAbsent(ERROR_FLOW_KEY, MutableSharedFlow())
44+
}
45+
46+
fun <T> Flow<T>.bindLoading(viewModel: ViewModel): Flow<T> {
47+
return this
48+
.onStart {
49+
viewModel.getLoadingMutableStateFlow().value = true
50+
}
51+
.onCompletion {
52+
viewModel.getLoadingMutableStateFlow().value = false
53+
}
54+
}
55+
fun <T> Flow<UseCaseResult<T>>.bindError(viewModel: ViewModel): Flow<UseCaseResult<T>> {
56+
return this
57+
.onError {
58+
viewModel.emitViewError(it.mapToViewError())
59+
}
60+
}

app/src/main/java/com/monstarlab/features/login/LoginFragment.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ package com.monstarlab.features.login
33
import android.os.Bundle
44
import android.view.View
55
import androidx.lifecycle.lifecycleScope
6-
import androidx.lifecycle.viewModelScope
6+
import androidx.lifecycle.loadingFlow
7+
import androidx.lifecycle.viewErrorFlow
78
import androidx.navigation.fragment.findNavController
89
import androidx.transition.TransitionManager
910
import com.google.android.material.snackbar.Snackbar
@@ -15,7 +16,6 @@ import com.monstarlab.arch.extensions.viewBinding
1516
import com.monstarlab.databinding.FragmentLoginBinding
1617
import kotlinx.coroutines.flow.launchIn
1718
import kotlinx.coroutines.flow.onEach
18-
import kotlinx.coroutines.launch
1919

2020
class LoginFragment : BaseFragment(R.layout.fragment_login) {
2121

@@ -36,7 +36,7 @@ class LoginFragment : BaseFragment(R.layout.fragment_login) {
3636
findNavController().navigate(R.id.resourceFragment)
3737
}
3838

39-
collectFlow(viewModel.errorFlow) { viewError ->
39+
collectFlow(viewModel.viewErrorFlow) { viewError ->
4040
Snackbar.make(view, viewError.message, Snackbar.LENGTH_SHORT).show()
4141
}
4242

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,28 @@
11
package com.monstarlab.features.login
22

33
import androidx.lifecycle.ViewModel
4+
import androidx.lifecycle.bindError
5+
import androidx.lifecycle.bindLoading
46
import androidx.lifecycle.viewModelScope
5-
import com.monstarlab.arch.extensions.onError
67
import com.monstarlab.arch.extensions.onSuccess
7-
import com.monstarlab.core.sharedui.errorhandling.ViewError
8-
import com.monstarlab.core.sharedui.errorhandling.mapToViewError
98
import com.monstarlab.core.usecases.user.LoginUseCase
10-
import kotlinx.coroutines.flow.*
9+
import kotlinx.coroutines.flow.MutableSharedFlow
10+
import kotlinx.coroutines.flow.launchIn
1111
import javax.inject.Inject
1212

1313
class LoginViewModel @Inject constructor(
1414
private val loginUseCase: LoginUseCase
15-
): ViewModel() {
16-
17-
val loadingFlow: MutableStateFlow<Boolean> = MutableStateFlow(false)
18-
val errorFlow: MutableSharedFlow<ViewError> = MutableSharedFlow()
15+
) : ViewModel() {
1916
val loginResultFlow: MutableSharedFlow<Boolean> = MutableSharedFlow()
2017

2118
fun login(email: String, password: String) {
2219
loginUseCase
2320
.login(email, password)
24-
.onStart {
25-
loadingFlow.value = true
26-
}.onSuccess {
21+
.bindLoading(this)
22+
.bindError(this)
23+
.onSuccess {
2724
loginResultFlow.emit(true)
28-
}.onError {
29-
errorFlow.emit(it.mapToViewError())
30-
}.onCompletion {
31-
loadingFlow.value = false
32-
}.launchIn(viewModelScope)
25+
}
26+
.launchIn(viewModelScope)
3327
}
34-
3528
}

0 commit comments

Comments
 (0)