Android 分页库无法正确向上滚动
Android Paging Library Doesn't Scroll Up Correctly
我正在通过网络调用(无数据库)使用 JetPack 分页库。
我能够顺畅地向下滚动并加载新的数据页,但是,当向上滚动时它会卡顿并快速跳到列表的顶部。我无法顺畅地向上滚动。
这是显示问题的视频:https://imgur.com/a/bRoelyF
我尝试过的:
- 启用改装缓存
- 使用 LinearLayoutManager 而不是 GridLayoutManager
- 使用库的 1.0.1 和 2.1.2 版本学习新旧教程
这是我的代码:
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)
现在可以正常加载了。
另一个考虑因素是图像的大小,加载较大的图像需要一段时间,尤其是当您在无限滚动中加载许多图像时。
我正在通过网络调用(无数据库)使用 JetPack 分页库。
我能够顺畅地向下滚动并加载新的数据页,但是,当向上滚动时它会卡顿并快速跳到列表的顶部。我无法顺畅地向上滚动。
这是显示问题的视频:https://imgur.com/a/bRoelyF
我尝试过的:
- 启用改装缓存
- 使用 LinearLayoutManager 而不是 GridLayoutManager
- 使用库的 1.0.1 和 2.1.2 版本学习新旧教程
这是我的代码:
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)
现在可以正常加载了。
另一个考虑因素是图像的大小,加载较大的图像需要一段时间,尤其是当您在无限滚动中加载许多图像时。