LiveData无法持续更新视图

时间:2019-07-05 11:40:06

标签: android kotlin android-recyclerview viewmodel android-livedata

在初始加载时,recycleView不会从网络更新结果。

RecycleView:


    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)

        mRecyclerAdapter = MovieListAdapter(context)

        rvMovieList.apply {
            // Dedicated layouts for Screen Orientation
            if (resources.configuration.orientation == Configuration.ORIENTATION_PORTRAIT) {
                layoutManager = LinearLayoutManager(context)
            } else {
                layoutManager = GridLayoutManager(context, 2)
            }

            adapter = mRecyclerAdapter
        }
    }

并使用ViewModel中的LiveData收听网络结果。

LiveData收听以下片段:

    override fun onResume() {
        super.onResume()

        // Listen to data change
        viewModel.getMovies().observe(this, mMovieListObserver)
    }

    private val mMovieListObserver: Observer<PagedList<MovieItem>> = Observer { movieItems ->
        Log.d(TAG, "MovieItems: ${movieItems.size}")
        showEmptyList(movieItems?.size == 0)
        mRecyclerAdapter.submitList(movieItems)
    }

    private fun showEmptyList(isEmpty: Boolean) {
        tvEmptyListView.visibility = if (isEmpty) View.VISIBLE else View.GONE
        rvMovieList.visibility = if (isEmpty) View.GONE else View.VISIBLE
    }

    override fun onPause() {
        viewModel.getMovies().removeObserver(mMovieListObserver)

        super.onPause()
    }

具有讽刺意味的是,结果在后续加载中填充了recycleView。我觉得LiveData无法正常工作。引入emptyView时的期望是基于网络的结果显示/隐藏recycleView / EmptyView。

下面粘贴的ViewModel:


class MovieListViewModel : ViewModel() {

    private val PAGE_SIZE = 10

     internal var movies: LiveData<PagedList<MovieItem>>

    init {
        val dataSourceFactory = MovieDataSourceFactory()

        val pagedListConfig = PagedList.Config.Builder()
                .setInitialLoadSizeHint(PAGE_SIZE)
                .setPageSize(PAGE_SIZE)
                .setEnablePlaceholders(true)
                .build()

        movies = LivePagedListBuilder(dataSourceFactory, pagedListConfig)
                // .setBoundaryCallback() TODO
                .build()
    }

    fun getMovies(): LiveData<PagedList<MovieItem>> {
        return movies
    }
}

感谢您的宝贵时间,感谢您对解决方案或最佳实践的任何投入。谢谢。

回购:https://gitlab.com/faisalm/MovieDirect

//// ---

更新了DataSourceFactory和DataSource。

class MovieDataSourceFactory : DataSource.Factory<Int, MovieItem>() {

    private val mutableLiveData = MutableLiveData<MovieDataSource>()

    override fun create(): DataSource<Int, MovieItem> {
        val dataSource = MovieDataSource()
        mutableLiveData.postValue(dataSource)
        return dataSource
    }
}


class MovieDataSource internal constructor() : PageKeyedDataSource<Int, MovieItem>() {

    private val movieDbService: MovieDbService = RetrofitFactory.create()

    override fun loadInitial(params: LoadInitialParams<Int>, callback: LoadInitialCallback<Int, MovieItem>) {

        val moviesListCall = movieDbService.fetchLatestMoviesPaged(Constants.API_KEY, 1)
        moviesListCall.enqueue(object : Callback<MoviesList> {
            override fun onResponse(call: Call<MoviesList>, response: Response<MoviesList>) {

                if (response.isSuccessful) {
                    val moviesLists = response.body()?.results
                    callback.onResult(moviesLists!!, 1, 2)
                }
            }

            override fun onFailure(call: Call<MoviesList>, t: Throwable) {}
        })
    }

    override fun loadBefore(params: LoadParams<Int>, callback: LoadCallback<Int, MovieItem>) {}

    override fun loadAfter(params: LoadParams<Int>, callback: LoadCallback<Int, MovieItem>) {

        val moviesListCall = movieDbService.fetchLatestMoviesPaged(Constants.API_KEY, params.key)

        moviesListCall.enqueue(object : Callback<MoviesList> {
            override fun onResponse(call: Call<MoviesList>, response: Response<MoviesList>) {

                if (response.isSuccessful) {
                    val moviesLists = response.body()?.results
                    callback.onResult(moviesLists!!, params.key + 1)
                }
            }

            override fun onFailure(call: Call<MoviesList>, t: Throwable) {}
        })
    }
}

1 个答案:

答案 0 :(得分:0)

我认为问题在于您为liveData添加和删除观察者的方式。

与其在onResume中添加和在onPause中删除,不如在片段的onActivityCreated中观察它。 LiveData的observe方法采用了LifeCycleOwner(这是您在Fragment中使用this传递的内容),并将确保在该生命周期中的正确时间进行观察。

因此删除这些行:

viewModel.getMovies().removeObserver(mMovieListObserver) viewModel.getMovies().addObserver(this, mMovieListObserver)

并添加以下内容:

override fun onActivityCreated(savedInstanceState: Bundle?) {
    super.onActivityCreated(savedInstanceState)
    viewModel.getMovies().observe(this, Observer { movieItems ->
        Log.d(TAG, "MovieItems: ${movieItems.size}")
        showEmptyList(movieItems?.loadedCount == 0)
        mRecyclerAdapter.submitList(movieItems)
    })
}