Issue
I'm learning flows and implementing them in my project, but I'm not sure I understood everything.
This is my model
data class ResultResponse (
@field:Json(name = "count") val count : Int?,
@field:Json(name = "favorites") val "favorites") : List<Favorite>?
)
This is my service
@GET("...")
suspend fun getFavorites(@Path("visitor") visitor: String) : Response<ApiModel<ResultResponse>>
This is my repository
suspend fun getFavorites(visitor: String) = flow {
emit(apiCall { api.getFavorites(visitor) })
}.onStart {
emit(State.loading())
}
Where apiCall is
suspend fun <T> apiCall(call: suspend () -> Response<T>): State<T>
This is my view model
private val parentJob = Job()
private val coroutineContext: CoroutineContext
get() = parentJob + Dispatchers.Default
private val scope = CoroutineScope(coroutineContext)
private val repository = FavoriteRepository(Api.favoriteService)
private val _favorites = MutableLiveData<State<ApiModel<ResultResponse>>>()
val favorites: LiveData<State<ApiModel<ResultResponse>>>
get() = _favorites
fun fetchFavorites() {
scope.launch {
repository.getFavorites(Preferences.visitor).collect {
_favorites.postValue(it)
}
}
}
This is my fragment
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
observer()
}
override fun onResume() {
super.onResume()
favoriteViewModel.fetchFavorites()
}
private fun observer() {
favoriteViewModel.favorites.observe(viewLifecycleOwner) { state ->
when (state) {
is State.Loading -> doSomethingOnLoadingState()
is State.Success -> doSomethingOnSuccessState(state)
is State.Error -> doSomethingOnErrorState(state)
}
}
}
The issue is when I switch fragment and come back to this one, it observes again the last state, so I got State.Success then State.Loading then State.Success triggered. I tried to solve it using an Event and getContentIfNotHandled()? but it didn't change anything.
And the second question is did I do it right, is this the best way to do it currently?
Solution
Everything works as expected. After returning to the fragment, your LiveData still holds previous Success state, then gets another Loading and Success from repository.
For me, having a loading
state in your repository doesn't seem right. I'd move it to ViewModel and then emit it only if necessary(if you actually want to show it in view), e.g. by checking current liveData state or by having a boolean flag in fetchFavourites method.
As for the second question - as always - it depends. I, personally wouldn't create a flow for a single api call, but would rather use a suspend function.
Answered By - r2rek
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.