Android效能優化——列表類控制元件卡頓優化

小欣兒發表於2018-07-19

原文連結:列表類控制元件卡頓優化

1、使用ConstraintLayout減少佈局層級。

2、可以的話,設定RecyclerView佈局等高,然後設定recyclerView.setHasFixedSize(true)這樣可以避免每次繪製Item時,不再重新計算Item高度。

3、根據需求修改RecyclerView預設的繪製快取選項

 recyclerView.setItemViewCacheSize(20);
 recyclerView.setDrawingCacheEnabled(true);
 recyclerView.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH);

4、在onBindViewHolder/getView方法中,減少邏輯判斷,減少臨時物件建立。例如:複用事件監聽,在其方法外部建立監聽,可以避免生成大量的臨時變數。
減少邏輯判斷參考方案:

 //優化前:
    class MyRecyclerView.Adapter extends RecyclerView.Adapter {

        static final TODAYS_DATE = new Date();
        static final DATE_FORMAT = new SimpleDateFormat("MM dd, yyyy");
        public onBindViewHolder(Task.ViewHolder tvh, int position) {
            Task task = getItem(position);
            if (TODAYS_DATE.compareTo(task.dateDue) > 0) {
                tvh.backgroundView.setColor(Color.GREEN);
            } else {
                tvh.backgroundView.setColor(Color.RED);
            }
            String dueDateFormatted = DATE_FORMAT.format(task.getDateDue());
            tvh.dateTextView.setDate(dueDateFormatted);
        }
    }
    //優化後,改寫model
    public class TaskViewModel {
        int overdueColor;
        String dateDue;
    }

    public onBindViewHolder(Task.ViewHolder tvh, int position) {    
        TaskViewModel taskViewModel = getItem(position);
        tvh.backgroundView.setColor(taskViewModel.getOverdueColor());
        tvh.dateTextView.setDate(taskViewModel.getDateDue());
    }

6、避免整個列表的資料更新,只更新受影響的佈局。例如,載入更多時,不使用notifyDataSetChanged(),而是使用notifyItemRangeInserted(rangeStart, rangeEnd)

7、scrollingCache=false animationCache=false(針對ListView)
scrollingCache: scrollingCache本質上是drawing cache,你可以讓一個View將他自己的drawing儲存在cache中(儲存為一個bitmap),這樣下次再顯示View的時候就不用重畫了,而是從cache中取出。預設情況下drawing cahce是禁用的,因為它太耗記憶體了,但是它確實比重畫來的更加平滑。而在ListView中,scrollingCache是預設開啟的,我們可以手動將它關閉。
animateCache: ListView預設開啟了animateCache,這會消耗大量的記憶體,因此會頻繁呼叫GC,我們可以手動將它關閉掉。

8、對於RecyclerView,持有item具有的獨特id,可以很容易地確定具體item並單獨更新,當變化發生時,可以按照如下方式更新,從而避免整體重新整理:

adapter.setHasStableIds(true);
adapter.notifyItemRemoved(position);    
adapter.notifyItemChanged(position);
adapter.notifyItemInserted(position);

參考:

https://stackoverflow.com/questions/27188536/recyclerview-scrolling-performance
https://stackoverflow.com/questions/27993627/optimizing-recyclerview-listview
另外附上一個大神寫的Adapter優化:http://www.jianshu.com/p/411ab861034f 其實現有用到以上部分思路。

相關文章