#android #kotlin #mvvm #flow
#Android #kotlin #mvvm #kotlin-flow
Вопрос:
Я изучаю потоки и внедряю их в свой проект, но я не уверен, что все понял.
Это моя модель
data class ResultResponse (
@field:Json(name = "count") val count : Int?,
@field:Json(name = "favorites") val "favorites") : List<Favorite>?
)
Это мой сервис
@GET("...")
suspend fun getFavorites(@Path("visitor") visitor: String) : Response<ApiModel<ResultResponse>>
Это мой репозиторий
suspend fun getFavorites(visitor: String) = flow {
emit(apiCall { api.getFavorites(visitor) })
}.onStart {
emit(State.loading())
}
Где ApiCall
suspend fun <T> apiCall(call: suspend () -> Response<T>): State<T>
Это моя модель представления
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)
}
}
}
Это мой фрагмент
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)
}
}
}
Проблема в том, что когда я переключаю фрагмент и возвращаюсь к этому, он снова наблюдает последнее состояние, поэтому я получил состояние.Затем укажите состояние успеха.Загрузка затем состояние.Срабатывает успешно. Я пытался решить это с помощью события и getContentIfNotHandled()? но это ничего не изменило.
И второй вопрос: правильно ли я все сделал, это лучший способ сделать это в настоящее время?
Комментарии:
1.
fetchFavorites()
срабатывает отonResume()
и, как и ожидалось, каждый раз2. Да, я хочу обновлять список каждый раз, когда пользователь открывает представление. Первый раз работает хорошо, во второй раз я заметил, что он несколько раз вызывал моего наблюдателя (предыдущее состояние новое состояние).
Ответ №1:
Все работает так, как ожидалось. После возврата к фрагменту ваши LiveData по-прежнему сохраняют предыдущее состояние успеха, затем получают другую загрузку и успех из репозитория.
Для меня наличие loading
состояния в вашем репозитории кажется неправильным. Я бы переместил его в ViewModel, а затем отправил бы его только при необходимости (если вы действительно хотите показать его в поле зрения), например, путем проверки текущего состояния LiveData или с помощью логического флага в методе fetchFavourites.
Что касается второго вопроса — как всегда — это зависит. Я лично не стал бы создавать поток для одного вызова api, а предпочел бы использовать функцию приостановки.
Комментарии:
1. Но я не хочу удерживать предыдущее состояние, потому что оно срабатывает два раза в моей функции doSomethingOnSuccessState (состояние).