21

我有一个类似聊天的活动,我正在使用带有 PagedListAdaper 的 RecyclerView 来加载一堆消息。我正在使用 PositionalDataSource 来加载数据。加载它自己工作正常,但是当我发送消息时,我使我的数据源无效并且列表被重新制作。我的问题是它这样做时会闪烁

这就是它的样子

我尝试添加 setHasStableIds(true) 并覆盖 getItemId 这将在一个简单的适配器上工作,但它似乎在这里不起作用。我似乎也不能只向 getCurrentList() 添加一个项目,因为它不受支持。另外,我没有使用数据库,只是向服务器发出请求。

所以我的问题是,除了使数据源无效之外,还有更好的方法吗?发送消息时有没有办法阻止列表闪烁?还是这个库不适合我的聊天活动?

编辑

我的差异回调

private val DIFF_CALLBACK: DiffCallback<MessageModel> = object : DiffCallback<MessageModel>() {
        override fun areItemsTheSame(@NonNull oldMessage: MessageModel, @NonNull newMessage: MessageModel) =
                oldMessage.id == newMessage.id


        override fun areContentsTheSame(@NonNull oldMessage: MessageModel, @NonNull newMessage: MessageModel) =
                oldMessage.equals(newMessage)
    }

Edit2 我修好了

所以我设法通过使用 PagedListAdapterHelper 并在加载项目后设置它的列表来修复它:

private var mHelper: PagedListAdapterHelper<MessageModel>? = null

init {
    mHelper = PagedListAdapterHelper(this, DIFF_CALLBACK)
    setHasStableIds(true)
}
fun setList(pagedList: PagedList<MessageModel>) {
    pagedList.addWeakCallback(pagedList.snapshot(), object:PagedList.Callback() {
        override fun onChanged(position: Int, count: Int) {

        }

        override fun onInserted(position: Int, count: Int) {
            mHelper?.setList(pagedList)
        }

        override fun onRemoved(position: Int, count: Int) {

        }

    })
}
4

5 回答 5

3

PagedListAdapterHelper 在分页组件中已弃用,因此我们应该使用AsyncPagedListDiffer代替它。

代码示例:

    import android.arch.paging.AsyncPagedListDiffer;
    import android.arch.paging.PagedList;
    import android.arch.paging.PagedListAdapter;
    import android.support.annotation.NonNull;
    import android.support.v7.util.DiffUtil;
    import android.view.LayoutInflater;
    import android.view.ViewGroup;


    public class PagedItemsArrayAdapter extends PagedListAdapter<Item, MyViewHolder> {

            private final AsyncPagedListDiffer<Item> mDiffer;

            public PagedItemsArrayAdapter() {
                super(DIFF_CALLBACK);
                mDiffer = new AsyncPagedListDiffer<>(this, DIFF_CALLBACK);
                setHasStableIds(true);
            }

            @Override
            public long getItemId(int position) {
               Item item = mDiffer.getItem(position);
               return item.id;
            }

            @Override
            public int getItemCount() {
                return mDiffer.getItemCount();
            }

            @Override
            public void submitList(PagedList<Item> pagedList) {

                pagedList.addWeakCallback(pagedList.snapshot(), new PagedList.Callback() {
                    @Override
                    public void onChanged(int position, int count) {
                    }

                    @Override
                    public void onInserted(int position, int count) {
                        mDiffer.submitList(pagedList);
                    }

                    @Override
                    public void onRemoved(int position, int count) {

                    }
                });

            }


            @Override
            public void onBindViewHolder(@NonNull MyViewHolder viewHolder, int position) {
                   Item item = mDiffer.getItem(position);
                   viewHolder.onBind(item); 
            }

            private static DiffUtil.ItemCallback<Item> DIFF_CALLBACK = new DiffUtil.ItemCallback<Item>() {
                @Override
                public boolean areItemsTheSame(@NonNull Item oldItem, @NonNull Item newItem) {
                    return oldItem.getId() == newItem.getId();
                }

                @Override
                public boolean areContentsTheSame(@NonNull Item oldItem, @NonNull Item newItem) {
                    return oldItem.equals(newItem);
                }
            };
于 2019-01-30T14:03:28.053 回答
3

简短的回答:确保同步调用callbackof而不将其包装在某种异步成功处理程序中。PositionalDataSource<T>.loadInitial(@NonNull LoadInitialParams params, @NonNull LoadInitialCallback<T> callback)loadInitial

解释:

闪烁可能是由初始加载中的异步加载引起的,即在PositionalDataSource<T>.loadInitial(@NonNull LoadInitialParams params, @NonNull LoadInitialCallback<T> callback).

当您这样做时会发生以下情况:

您的数据源会失效,这会导致创建一个新的PagedList(使用 创建时LivePagedListBuilder)。这个新创建的分页列表将被传递给您的适配器,但它仍然是空的,因为您没有在初始加载中直接调用回调。只要您的回调被调用,这将导致一个空列表。这最终导致闪烁效果。

于 2018-03-25T18:11:27.833 回答
1

您可以禁用项目动画。

mRecyclerView.setItemAnimator(null);
于 2018-07-11T19:51:49.293 回答
0

我们正在使用paging library 3with room。在我们在数据库上写入一些下一页数据后,我们得到了闪烁、闪烁和滚动效果。因为我们设置PagingConfig'sinitialLoadSize不同于pageSize. 我们已经开始对它们使用相同的值,并且我们的问题已得到解决。

于 2021-02-03T12:18:20.690 回答
0

loadInitial您应该在and中使用同步loadAfter,即:

mLoadState.postValue(NetworkState.Loading);
try {
    mLoadState.postValue(NetworkState.DONE);
    ResultMessage<List<Achievement>> info = call.execute().body();
    if (info != null && info.isSuccess()) {
        List<Achievement> list = info.getData();
        callback.onResult(list, null, FIRST_PAGE + 1);
    }
} catch (IOException e) {
    mLoadState.postValue(NetworkState.ERROR);
    mRetry.postValue(() -> loadInitial(params, callback));
    Log.d(TAG, "fail!");
}
于 2020-10-20T02:52:13.587 回答