繁体   English   中英

为什么此分页库示例的性能远不只是回收者视图?

[英]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) {

        }
    });
}

但是,我只是使用静态项列表适配器构建了相同的示例,并且在我的模拟器上滚动起来似乎更加流畅。 我的代码中缺少什么吗?

这是我对可能使情况变得更糟的背后因素的怀疑:

  1. 在这种情况下, recyclerview.setHasFixedSize(true)有意义? (我确实还注意到,当我向下滚动然后返回到原始图像时,图像的大小是不同的?有没有办法防止这种情况?)
  2. 这是因为DIFF_CALLBACK中有些奇怪吗? 我真的不太了解这堂课的目的
  3. viewModel.getPhotosList().observe(this, adapter::submitList); 预计速度会变慢,因为它会使列表无效(与静态列表相比); 但是,这会导致5倍的延迟吗?
  4. 我注意到我在模拟器上跑得很快,在静态recyclerview上这似乎不是问题; 但是,LivePage对其窜动检测是否有所不同? 我猛扑时屏幕似乎发疯了。 换句话说,我感觉到的“来自分页库的锯齿性能”是否仅是因为我上下浮动(而不是缓慢地上下滚动)?
  5. 我只是在某个地方缺少关键配置设置吗?

当然,静态列表将更加平滑-开销要少得多。 如果实际可行,那就去吧。 当将整个列表保存在内存中不可行时,或者从数据源(尤其是远程数据源)请求整个列表太耗时/昂贵时,可以使用分页列表。

1)取决于您的UI。 固定大小是它在屏幕上显示的大小,而不是列表的大小。 通常,对于全尺寸列表或不随内容增长/缩小的列表而言,这是正确的。

2)DiffUtil及其回调与分页无关,它们已预先存在分页库。 它们围绕更改列出列表,以使对适配器的最有效调用成为可能,而不是执行整个notifyDataSetChanged。 但是他们确实花了一些时间。 重要的是要做到这一点正确,否则您将错过通知或使用效率较低的通知。

3)预计比什么慢? 但是在使用可观察对象的任何地方,您都会看到速度变慢,您可能会在线程之间发布消息。 这是他们很多时候被严重滥用的原因之一,人们不了解他们的实际工作。 是的,速度降低5倍似乎不太可能,尤其是如果您最终使用效率较低的notifyDataSetChanged而不是更精确的通知时。

4)猛扑时,您可以更快地装载更多物品。 这可能会导致更多的远程负载。 因此,如果您遇到问题,那将是您逃跑的时候。 通常,您要提前足够长的时间在单独的线程上预加载,这不是问题。 您是否尝试过页面大小和预取距离?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM