[英]Why does this example of paging library perform much worse than just a recycler view?
因此,我一直在閱讀Android的新分頁庫。 具體來說,我正在嘗試使用帶有適配器,視圖模型和數據源(由改造網絡調用支持)的recyclerview加載永無休止的圖像列表(使用Glide)。
這是基本代碼:
// inside my activity
PhotosListAdapter adapter = new PhotosListAdapter(getApplicationContext());
PhotosViewModel viewModel = ViewModelProviders.of(this).get(PhotosViewModel.class);
viewModel.getPhotosList().observe(this, adapter::submitList);
RecyclerView recyclerView = findViewById(R.id.main_recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setHasFixedSize(true);
recyclerView.setAdapter(adapter);
...
// My adapter code:
@Override
public void onBindViewHolder(@NonNull PhotoViewHolder photoViewHolder, int i) {
Photo photo = getItem(i);
if (photo != null) {
mGlide.load(photo.previewURL).into(photoViewHolder.mPhotoImageView);
}
}
private static final DiffUtil.ItemCallback<Photo> DIFF_CALLBACK = new DiffUtil.ItemCallback<Photo>() {
@Override
public boolean areItemsTheSame(@NonNull Photo photo, @NonNull Photo other) {
return photo.id == other.id; // these are just ints
}
@Override
public boolean areContentsTheSame(@NonNull Photo photo, @NonNull Photo other) {
return photo.previewURL.equals(other.previewURL); // this is just a string
}
};
...
// My View Model code:
private LiveData<PagedList<Photo>> mData;
public PhotosViewModel() {
PhotosDataSource photosDataSource = new PhotosDataSource();
mData = new LivePagedListBuilder<>(new DataSource.Factory<Integer, Photo>() {
@Override
public DataSource<Integer, Photo> create() {
return photosDataSource;
}
}, 25).build();
}
public LiveData<PagedList<Photo>> getPhotosList() {
return mData;
}
// My Data Source:
Call<SearchResult> search = mPixabayService.search(PixabayApi.api_key, "photo", 1, params.requestedLoadSize, true);
search.enqueue(new Callback<SearchResult>() {
@Override
public void onResponse(Call<SearchResult> call, Response<SearchResult> response) {
if (response.isSuccessful()) {
SearchResult body = response.body();
callback.onResult(body.hits, null, 2);
}
// TODO add error cases
}
@Override
public void onFailure(Call<SearchResult> call, Throwable t) {
}
});
@Override
public void loadAfter(@NonNull LoadParams params, @NonNull LoadCallback callback) {
Call<SearchResult> result = mPixabayService.search(PixabayApi.api_key, "photo", (Integer)params.key, params.requestedLoadSize, true);
result.enqueue(new Callback<SearchResult>() {
@Override
public void onResponse(Call<SearchResult> call, Response<SearchResult> response) {
if (response.isSuccessful()) {
List<Photo> hits = response.body().hits;
callback.onResult(hits, (Integer)params.key + 1);
}
}
@Override
public void onFailure(Call<SearchResult> call, Throwable t) {
}
});
}
但是,我只是使用靜態項列表適配器構建了相同的示例,並且在我的模擬器上滾動起來似乎更加流暢。 我的代碼中缺少什么嗎?
這是我對可能使情況變得更糟的背后因素的懷疑:
recyclerview.setHasFixedSize(true)
有意義? (我確實還注意到,當我向下滾動然后返回到原始圖像時,圖像的大小是不同的?有沒有辦法防止這種情況?) DIFF_CALLBACK
中有些奇怪嗎? 我真的不太了解這堂課的目的 viewModel.getPhotosList().observe(this, adapter::submitList);
預計速度會變慢,因為它會使列表無效(與靜態列表相比); 但是,這會導致5倍的延遲嗎? 當然,靜態列表將更加平滑-開銷要少得多。 如果實際可行,那就去吧。 當將整個列表保存在內存中不可行時,或者從數據源(尤其是遠程數據源)請求整個列表太耗時/昂貴時,可以使用分頁列表。
1)取決於您的UI。 固定大小是它在屏幕上顯示的大小,而不是列表的大小。 通常,對於全尺寸列表或不隨內容增長/縮小的列表而言,這是正確的。
2)DiffUtil及其回調與分頁無關,它們已預先存在分頁庫。 它們圍繞更改列出列表,以使對適配器的最有效調用成為可能,而不是執行整個notifyDataSetChanged。 但是他們確實花了一些時間。 重要的是要做到這一點正確,否則您將錯過通知或使用效率較低的通知。
3)預計比什么慢? 但是在使用可觀察對象的任何地方,您都會看到速度變慢,您可能會在線程之間發布消息。 這是他們很多時候被嚴重濫用的原因之一,人們不了解他們的實際工作。 是的,速度降低5倍似乎不太可能,尤其是如果您最終使用效率較低的notifyDataSetChanged而不是更精確的通知時。
4)猛撲時,您可以更快地裝載更多物品。 這可能會導致更多的遠程負載。 因此,如果您遇到問題,那將是您逃跑的時候。 通常,您要提前足夠長的時間在單獨的線程上預加載,這不是問題。 您是否嘗試過頁面大小和預取距離?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.