LiveData не обновляет представление последовательно - PullRequest
0 голосов
/ 05 июля 2019

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

и прослушивание сетевого результата с использованием LiveData из ViewModel.

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 голосов
/ 06 июля 2019

Я думаю, проблема в том, как вы добавляете и удаляете наблюдателя для liveData.

Вместо добавления в onResume и удаления в onPause, просто наблюдайте в onActivityCreated вФрагмент.Метод наблюдения LiveData принимает LifeCycleOwner (то, что вы передаете с 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)
    })
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...