簡體   English   中英

如何使用架構組件分頁庫停止在回收站視圖上閃爍

[英]How to stop blinking on recycler view with architecture components paging library

我有一個類似聊天的活動,我使用帶有 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) {

        }

    })
}

簡短的回答:請確保調用的callbackPositionalDataSource<T>.loadInitial(@NonNull LoadInitialParams params, @NonNull LoadInitialCallback<T> callback)同步在loadInitial沒有某種異步成功處理程序的包裝它。

說明:

閃爍可能是由初始加載中的異步加載引起的,即在PositionalDataSource<T>.loadInitial(@NonNull LoadInitialParams params, @NonNull LoadInitialCallback<T> callback)

這樣做時會發生以下情況:

您的數據源失效,導致創建新的PagedList (使用LivePagedListBuilder創建時)。 這個新創建的分頁列表將傳遞給您的適配器,但它仍然是空的,因為您沒有在初始加載時直接調用回調。 只要您的回調被調用,這將導致一個空列表。 這最終導致閃爍效果。

PagedListAdapterHelper 在 Paging Component 中已棄用,因此我們應該使用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);
                }
            };

您可以禁用項目動畫。

mRecyclerView.setItemAnimator(null);

您應該在loadInitialloadAfter使用同步,即:

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!");
}

我們正在使用帶有room paging library 3 在我們在數據庫上寫了一些下一頁數據后,我們得到了閃爍、閃爍和滾動的效果。 因為我們將PagingConfiginitialLoadSize設置為與pageSize不同。 我們已經開始對它們使用相同的值,我們的問題已經解決。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM