简体   繁体   English

Android jetpack 撰写观察实时数据

[英]Android jetpack compose observing a livedata

I have question regarding using observeAsState() to automatically populate a composable list view.我有关于使用observeAsState()自动填充可组合列表视图的问题。

My composable looks like this我的组合看起来像这样

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

This uses MVVM to do a network call to fetch some list of data and return it it back as a livedata.这使用 MVVM 进行网络调用以获取一些数据列表并将其作为实时数据返回。

The issue i am having is that it seems stuck on a infinit loop.我遇到的问题是它似乎卡在无限循环中。 If i dont use observeeAsState and just use the normal none composable way ie:如果我不使用observeeAsState而只使用正常的不可组合方式,即:

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

it works as expected and executes and ends once a error or a success is returned from the repository/domain layer.一旦从存储库/域层返回错误或成功,它就会按预期工作并执行并结束。

This is the createMovieItemView below:这是下面的 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)

        })
    } 

to automatically populate a composable list view.自动填充可组合列表视图。

My composable looks like this我的组合看起来像这样

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

This uses MVVM , to do a network call to fetch some list of data and then returns a livedata.这使用MVVM进行网络调用以获取一些数据列表,然后返回一个实时数据。

Issue seems to be, it stuck in a infinit loop.问题似乎是,它陷入了无限循环。 If i dont use observeeAsState and just use the normal none composable way ie movieListViewModel.getTopMovies().observe(viewLifecycleOwner, Observer { it works as expected, executes and ends once an error or a success is returned from the repository/domain layer.如果我不使用observeeAsState 而只是使用正常的非可组合方式,即movieListViewModel.getTopMovies().observe(viewLifecycleOwner, Observer { 它按预期工作,一旦从存储库/域层返回错误或成功,它就会执行并结束。

I had a similar problem and I solved by wrapping getTopMovies inside a LaunchedEffect block and I end up with something like this:我有一个类似的问题,我通过将getTopMovies包装在LaunchedEffect块中解决了,我最终得到了这样的结果:

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

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

Whereas the viewModel would be something like:而 viewModel 将类似于:

class MoviesViewModel(): ViewModel {

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

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

Note this is pseudo-code to describe the solution.请注意,这是描述解决方案的伪代码。 Which is inspired on rememberUpdatedState extample灵感来自于rememberUpdatedState 示例

If getTopMovies uses co-routines, it has side-effects, therefore LaunchedEffect is needed because Composables should be side-effect free as it is described at Side-effects in Compose .如果getTopMovies使用协程,则它有副作用,因此需要LaunchedEffect ,因为Composables 应该是无副作用的,如 Compose 中的副作用中所述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM