安卓 RecyclerView局部刷新

 

 

  在我們的開發中,RecyclerView是使用非常頻繁的,除了常用的列表展示之外,很多時候我們要根據item的操作進行列表的刷新,比如勾選列表的勾選、刪除或者根據操作動態設置某個item的佈局。這時候,大部分人包括我在內使用的都是這種方式:修改數據源list,然後調用adapter的notifyDataSetChanged()進行刷新。

   這種方式是我們經常採用的,在數據量比較小或者大部分的場景下都是適用的。但是這種方式卻是最浪費性能的,只在少部分情況下合適。很多情況下並不合適,比如一個勾選列表,我們進行多選的時候,如果每選一次就進行一次notifyDataSetChanged,相當於因爲針對一個item的操作而刷新整個列表中所有的item,這對於RecyclerView的性能是種損害,也不夠聰明,通過緩存勾選狀態的數據,我們可以使用全局刷新的方式完成想要的結果,但這不是最佳的方式,人都要有點追求,代碼也一樣。我們可以使用局部刷新的方式,爲什麼要進行全局刷新?

   而RecyclerView的本身就爲我們提供了局部刷新的方式,在adpter中,有這個方法,它跟我們常用的onBindViewHolder很像,只是多了一個參數,我們就是利用這個參數實現局部刷新的功能,這個參數就是最後面的payloads

public void onBindViewHolder(VHholder, int position, List<Object> payloads) {
            onBindViewHolder(holder, position);
        }

因爲這個方法多了一個payloads,而且它會在我們不僅可以利用這個payloads進行邏輯判斷,還能傳參,它是List<Object>類型的數據,這可以說說是我們最方便使用的數據類型,我們可以往裏面放我們的任何類型的數據,從對象到字符串、布爾值、整型或者對象集合等。
  而這個帶payloads的onBindViewHolder會在觸發notifyItemChanged(int position, @Nullable Object payload)方法後調用,這個方法我們通過英文也能知道,是刷新指定position的item,並且可以傳遞一個object類型的payloads參數。
拿我實際的項目需求舉例,  
                               
如上圖,item的下方有一個按鈕“收起課表”(”展開課表“),我們的需求是在點擊”展開課表“時候進行再接口請求,獲取那些第幾講的數據(別問爲什麼不一次請求完所有數據,就是這個需求),然後課表要有展開的動畫(這個動畫我個人感覺可以再寫個博客,哈哈),這就需要我進行item的局部刷新,那麼如何刷新?
     當點擊”展開課表"的接口的時候,回調activity中的接口調用,然後再接口中做完數據的安全判斷後只需要一行代碼courseArrangementListAdapter.notifyItemChanged(unFoldItemPosition, baseResult.getResultData());
  notifyItemChanged第一個參數是要刷新的item的position,這個方法的第二個參數,就是onBindViewHolder(VHholder, int position, List<Object> payloads)的payloads,我把課表數據也就是payload傳過去,在onBindViewHolder中如下,通過對payload進行判斷以及取值,就可以只對position=unFoldItemPosition的item進行處理。
我在不帶payloads的onBindViewHolder中處理普通的業務處理,而在帶payloads的onBindViewHolder中進行刷新處理。
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position, @NonNull List<Object> payloads) {
    super.onBindViewHolder(holder, position, payloads);
    PlanListEntity.RowsBean bean = list.get(position);

    if (payloads.isEmpty()) {
        LogUtils.d("=========", "onBindViewHolder payload isEmpty ");
        onBindViewHolder(holder, position);
    } else {
        LogUtils.d("=========", "onBindViewHolder payload: " + payloads);
        List<CoursePlanTimetableEntity> timetableEntityList = (List<CoursePlanTimetableEntity>) payloads.get(0);
        if (timetableEntityList.size() > 0) {
            handleTimeView(timetableEntityList, holder);
        }
        if (holder.tvTimetableAction.getText().toString().equals(context.getString(R.string.fold_timetable))) {
            //展示展開課表動畫
            showTimetableUnfoldAnimator(timetableEntityList, holder);
        } else {
            //展示收起課表動畫
            showTimetableFoldAnimator(timetableEntityList, holder);
        }
    }
}
很簡單但是很實用,希望能幫助到看到這篇博客的朋友。

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章