Kotlin & flow & MVVM -> 切换片段时观察者触发多次

Kotlin & flow & MVVM -> observer triggered multiple time when switch fragment

我正在学习流程并在我的项目中实施它们,但我不确定我是否理解所有内容。

这是我的模型

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)
        }
    }
}

问题是当我切换片段并回到这个片段时,它再次观察到最后的状态,所以我触发了 State.Success 然后 State.Loading 然后 State.Success。我尝试使用 Event and getContentIfNotHandled()? 解决它,但它没有改变任何东西。

第二个问题是我做对了吗,这是目前最好的方法吗?

一切正常。返回片段后,您的 LiveData 仍保持先前的 Success 状态,然后从存储库中获取另一个 Loading 和 Success。

对我来说,在您的存储库中有一个 loading 状态似乎不对。我会将它移动到 ViewModel,然后仅在必要时发出它(如果你真的想在视图中显示它),例如通过检查当前 liveData 状态或在 fetchFavourites 方法中使用布尔标志。

至于第二个问题——一如既往——视情况而定。我个人不会为单个 api 调用创建流程,而是宁愿使用暂停功能。