gpt4 book ai didi

android - RecyclerView 使用 Room 和 PagingListAdapter 向下滚动数据更新

转载 作者:太空宇宙 更新时间:2023-11-03 10:57:30 24 4
gpt4 key购买 nike

我创建了一个示例项目来展示我在使用 RecyclerView、Room 和 Paging 时遇到的一个问题,即RecyclerView 意外地向下滚动数据更新

https://github.com/HappyPeng2x/RoomRecyclerViewExample

该应用有一个 Room 数据库,我使用派生自 PagedListAdapter 的适配器在 RecyclerView 中显示它的值。

如下面的代码所示,查询被观察到,因此表的每次更新都会被适配器反射(reflect)出来。

   PagedList.Config plConfig =
new PagedList.Config.Builder().setEnablePlaceholders(false)
.setPrefetchDistance(10)
.setPageSize(20).build();

new LivePagedListBuilder<>
(mDB.getMyDao().getAllPaged(), plConfig)
.build()
.observe(this, new Observer<PagedList<MyEntry>>() {
@Override
public void onChanged(PagedList<MyEntry> myList) {
adapter.submitList(myList);
}
});

为了测试,我用 1000 个键/值对填充表。 key从1开始到1000结束,value都以INITIAL初始化。

我在每个显示的元素中包含一个切换按钮;单击它会将值从 INITIAL 切换到 FINAL 并反转。

在第 155 个元素处按下切换按钮时,显示的值从 INITIAL 更改为 FINAL,没有任何问题。

在第 243 个元素上执行相同的操作时,按下按钮会导致 RecyclerView 向下滚动这不是预期的

每次在此位置周围按下按钮时,问题都会重复出现。

我拍摄了一段视频以便观察问题。

https://github.com/HappyPeng2x/RoomRecyclerViewExample/blob/master/videos/device-2019-02-02-105434.webm

我一直在为这个问题苦苦挣扎,并且感到有点惭愧,因为它似乎是架构组件的基本使用,所以我很乐意得到任何帮助。

最佳答案

此问题是一个错误,已由 Google 解决,修复应该包含在下一版本的 Paging 中,遗憾的是尚未发生。

问题跟踪器中的 URL 是 https://issuetracker.google.com/issues/123834703 - 然而,由于需要登录才能看到它,我将在此处复制主要元素。

正如开发人员所解释的那样,问题是库通常会在最后访问的位置 周围 触发初始加载,但是当禁用占位符时,此逻辑会被绕过,因此加载会发生 最后访问的位置。由于此位置通常是 RecyclerView 绑定(bind)的最后一个部分离开屏幕的项目,这意味着屏幕上的大部分项目在初始加载时都丢失了,并且只会在以后分页。

尚未发布包含此修复程序的版本,您必须使用开发版本,但您也可以添加开发人员在 https://github.com/HappyPeng2x/RoomRecyclerViewExample 为我的示例应用程序建议的解决方法.

1) 将以下类添加到 MainActivity.java:

static class RoomFactoryWrapper<T> extends DataSource.Factory<Integer, T> {
final DataSource.Factory<Integer, T> m_wrappedFactory;

RoomFactoryWrapper(@NonNull Factory<Integer, T> wrappedFactory) {
m_wrappedFactory = wrappedFactory;
}

@NonNull
@Override
public DataSource<Integer, T> create() {
return new DataSourceWrapper<>((PositionalDataSource<T>) m_wrappedFactory.create());
}

static class DataSourceWrapper<T> extends PositionalDataSource<T> {
final PositionalDataSource<T> m_wrappedSource;

DataSourceWrapper(PositionalDataSource<T> wrappedSource) {
m_wrappedSource = wrappedSource;
}

@Override
public void addInvalidatedCallback(@NonNull InvalidatedCallback onInvalidatedCallback) {
m_wrappedSource.addInvalidatedCallback(onInvalidatedCallback);
}

@Override
public void removeInvalidatedCallback(
@NonNull InvalidatedCallback onInvalidatedCallback) {
m_wrappedSource.removeInvalidatedCallback(onInvalidatedCallback);
}

@Override
public void invalidate() {
m_wrappedSource.invalidate();
}

@Override
public boolean isInvalid() {
return m_wrappedSource.isInvalid();
}

@Override
public void loadInitial(@NonNull LoadInitialParams params,
@NonNull LoadInitialCallback<T> callback) {
// Workaround for paging bug: https://issuetracker.google.com/issues/123834703
// edit initial load position to start 1/2 load ahead of requested position
int newStartPos = params.placeholdersEnabled
? params.requestedStartPosition
: Math.max(0, params.requestedStartPosition - (params.requestedLoadSize / 2));
m_wrappedSource.loadInitial(new LoadInitialParams(
newStartPos,
params.requestedLoadSize,
params.pageSize,
params.placeholdersEnabled
), callback);
}

@Override
public void loadRange(@NonNull LoadRangeParams params,
@NonNull LoadRangeCallback<T> callback) {
m_wrappedSource.loadRange(params, callback);
}
}
}

2) 在 dataSourceFactory 上使用包装器:

    new LivePagedListBuilder<>
(new RoomFactoryWrapper<>(mDB.getMyDao().getAllPaged()), plConfig)

关于android - RecyclerView 使用 Room 和 PagingListAdapter 向下滚动数据更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54489506/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com