【问题标题】:Android jetpack compose observing a livedataAndroid jetpack 撰写观察 livedata
【发布时间】:2020-11-10 15:33:50
【问题描述】:

我对使用 observeAsState() 自动填充可组合列表视图有疑问。

我的可组合看起来像这样

@Composable
    fun getTopMovies() {
        val topMovies by movieListViewModel.getTopMovies().observeAsState()
        when (topMovies?.status) {
            Status.Error -> Text("error")
            Status.Loading -> {
                Log.d("JJJ", "Loading ")
                Text(text = "Loading")
            }
            Status.Success -> createMovieItemView(topMovies?.data?.results.orEmpty())
        }
    }

这使用 MVVM 进行网络调用以获取一些数据列表并将其作为实时数据返回。

我遇到的问题是它似乎卡在无限循环中。如果我不使用observeeAsState,而只使用正常的不可组合方式,即:

movieListViewModel.getTopMovies().observe(viewLifecycleOwner, Observer { ...}

它按预期工作,一旦从存储库/域层返回错误或成功,它就会执行并结束。

这是下面的createMovieItemView:

    @Composable
    private fun createMovieItemView(movieList: List<MovieItem>) {
        LazyColumnFor(items = movieList, itemContent = { movieItem ->
            MovieListItem(MovieItemData(movieItem.posterPath.orEmpty(),
                    movieItem.title.orEmpty(),
                    movieItem.releaseDate.orEmpty(),
                    "some genra", ""), picasso)

        })
    } 

自动填充可组合的列表视图。

我的可组合看起来像这样

@Composable
    fun getTopMovies() {
        val topMovies by movieListViewModel.getTopMovies().observeAsState()
        when (topMovies?.status) {
            Status.Error -> Text("error")
            Status.Loading -> {
                Log.d("JJJ", "Loading ")
                Text(text = "Loading")
            }
            Status.Success -> createMovieItemView(topMovies?.data?.results.orEmpty())
        }
    }

这使用 MVVM,进行网络调用以获取一些数据列表,然后返回一个 livedata。

问题似乎是,它陷入了无限循环。如果我不使用observeeAsState,而只使用正常的不可组合方式,即movieListViewModel.getTopMovies().observe(viewLifecycleOwner, Observer {它按预期工作,一旦从存储库/域层返回错误或成功,它就会执行并结束。

【问题讨论】:

  • 我认为你应该熟悉 MutableStateFlow/StateFlow 机制,它们与 Jetpack Compose 一起工作得更好/更容易
  • 这就是我在上面的代码中发现使用 observeAs 的地方

标签: android kotlin state android-mvvm android-jetpack-compose


【解决方案1】:

我遇到了类似的问题,我通过将 getTopMovies 包装在 LaunchedEffect 块内解决了问题,最终得到如下结果:

@Composable
fun MoviesScreen(onTimeout: () -> Unit) {
    val topMovies by viewModel.topMovies.observeAsState()

    LaunchedEffect(true) {
       movieListViewModel.getTopMovies().observeAsState()
    }
}

而 viewModel 类似于:

class MoviesViewModel(): ViewModel {

   var _topMovies: MutableLiveData<List<Movies>> = mutableLiveDataOf(listOf())
   val topMovies: LiveData<List<Movies>>

   fun getTopMovies(){
      _topMovies.postValue(repository.getTopMovies())
   }
}

请注意,这是描述解决方案的伪代码。灵感来自rememberUpdatedState extample

如果getTopMovies 使用协程,它有副作用,因此需要LaunchedEffect,因为可组合项应该没有副作用,如Side-effects in Compose 所述。 p>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-26
    相关资源
    最近更新 更多