Android 分页库无法正确向上滚动

Android Paging Library Doesn't Scroll Up Correctly

我正在通过网络调用(无数据库)使用 JetPack 分页库。

我能够顺畅地向下滚动并加载新的数据页,但是,当向上滚动时它会卡顿并快速跳到列表的顶部。我无法顺畅地向上滚动。

这是显示问题的视频:https://imgur.com/a/bRoelyF

我尝试过的:

这是我的代码:

MovieDataSource.kt:

    private val movieDbApi: TheMovieDbApi
) : PageKeyedDataSource<Int, Movie>() {

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


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

        movieDbApi.getTopRatedMovies(BuildConfig.MOVIE_DATA_BASE_API, FIRST_PAGE).subscribe(
            {
                it?.let { callback.onResult(it.results, null, FIRST_PAGE + 1) }
            }, {}
        )
    }

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

        movieDbApi.getTopRatedMovies(BuildConfig.MOVIE_DATA_BASE_API, params.key).subscribe(
            {
                val key = params.key + 1
                it?.let {callback.onResult(it.results, key)
                }
            },{}
        )

    }

MovieDataSourceFactory.kt:

class MovieDataSourceFactory(private val movieDbApi: TheMovieDbApi) :
    DataSource.Factory<Int, Movie>() {

    // Is this where the MovieDataSource callBacks are sent?
    val movieLiveDataSource = MutableLiveData<MovieDataSource>()

    override fun create(): DataSource<Int, Movie> {
        val movieDataSource = MovieDataSource(movieDbApi)
        movieLiveDataSource.postValue(movieDataSource)
        return movieDataSource
    }

}

HomeViewModel.kt:

class HomeViewModel @Inject constructor(
    theMovieDbApi: TheMovieDbApi
) : DisposingViewModel() {

    var moviePagedList: LiveData<PagedList<Movie>>
    private var liveDataSource: LiveData<MovieDataSource>

    init {
        val movieDataSourceFactory = MovieDataSourceFactory(theMovieDbApi)
        liveDataSource = movieDataSourceFactory.movieLiveDataSource

        val config = PagedList.Config.Builder()
            .setEnablePlaceholders(true)
            .setPageSize(MovieDataSource.PAGE_SIZE)
            .build()

        moviePagedList = LivePagedListBuilder(movieDataSourceFactory, config)
            .build()
    }
}

HomeViewModel.kt:

class HomeActivity : AppCompatActivity() {

    @Inject
    internal lateinit var viewModelFactory: ViewModelFactory<HomeViewModel>
    private lateinit var viewModel: HomeViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_home)
        AndroidInjection.inject(this)

        val adapter = HomeAdapter()

        movie_recycler_view.setHasFixedSize(false)
        movie_recycler_view.layoutManager = LinearLayoutManager(this)

        val viewModel = ViewModelProvider(this, viewModelFactory).get(HomeViewModel::class.java)

        viewModel.moviePagedList.observe(this, Observer {
            adapter.submitList(it)
        })

        movie_recycler_view.adapter = adapter
}
}

HomeAdapter.kt:

class HomeAdapter : PagedListAdapter<Movie, HomeAdapter.MovieViewHolder>(USER_COMPARATOR) {

    override fun getItemCount(): Int {
        return super.getItemCount()
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MovieViewHolder {
        val view = LayoutInflater.from(parent.context)
            .inflate(R.layout.item_movie, parent, false)
        return MovieViewHolder(view)
    }

    override fun onBindViewHolder(holder: MovieViewHolder, position: Int) {
        val movie = getItem(position)
        movie?.let { holder.bind(it) }
    }


    class MovieViewHolder(view: View) : RecyclerView.ViewHolder(view) {

        fun bind(movie: Movie) {

            Picasso.get().load(BASE_IMAGE_URL + movie.poster_path).into(itemView.movie_image)

        }
    }

    companion object {
        private val USER_COMPARATOR = object : DiffUtil.ItemCallback<Movie>() {
            override fun areItemsTheSame(oldItem: Movie, newItem: Movie): Boolean =
                oldItem.id == newItem.id

            override fun areContentsTheSame(oldItem: Movie, newItem: Movie): Boolean =
                oldItem == newItem
        }
    }
}

如果有人有解决方案或发现问题,我很想听听!

我解决了问题。

这是因为我没有在适配器中为 Picasso 添加占位符图像。

之前:

Picasso.get()
    .load(BASE_IMAGE_URL + movie.poster_path)
    .into(itemView.movie_image)

之后:

Picasso.get()
    .load(BASE_IMAGE_URL + movie.poster_path)
    .placeholder(R.drawable.placeholder)
    .into(itemView.movie_image)

现在可以正常加载了。

另一个考虑因素是图像的大小,加载较大的图像需要一段时间,尤其是当您在无限滚动中加载许多图像时。