最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

android RecyclerView的一些優(yōu)化點(diǎn)介紹

 更新時間:2021年12月23日 10:40:11   作者:讓開,我要吃人了  
大家好,本篇文章主要講的是android RecyclerView的一些優(yōu)化點(diǎn)介紹,感興趣的同學(xué)趕快來看一看吧,對你有幫助的話記得收藏一下,方便下次瀏覽

1.RecycledPool的重用

場景以及使用:

多個RecyclerView出現(xiàn),并且他們的item布局結(jié)構(gòu)一致,這時候可以進(jìn)行重用。

在進(jìn)行RecyclerView的初始化設(shè)置時候進(jìn)行RecycledPool的設(shè)置。

 //每個單元的視頻列表的RecycledPool
    private var mRecycledViewPool: RecyclerView.RecycledViewPool? = null
 
unitVideoListContentRv.run {
                layoutManager = GridLayoutManager(itemView.context, 3)
                if (mRecycledViewPool != null) {
                    setRecycledViewPool(mRecycledViewPool)
                } else {
                    mRecycledViewPool = recycledViewPool
                }
                ...........
            }

重用前后的對比:

本次展示的是長列表中的item嵌套列表,進(jìn)行多item的加載然后上下滑動,同時檢測內(nèi)存的開銷占用。

image.png

列表的規(guī)模是13個item,每個item中有4個視頻item,規(guī)模不算特別大。

重用RecycledPool之前:

image.png

數(shù)據(jù)加載完畢之后,最后上下滑動的內(nèi)存趨于平穩(wěn)在48.4m

重用RecycledPool之后:

image.png

數(shù)據(jù)加載完畢之后,最后上下滑動的內(nèi)存趨于平穩(wěn)在40m。

對比總結(jié):

其實(shí)很明顯可以看到內(nèi)存開銷減少,而內(nèi)存開銷減少能提升列表的流暢度,效果是顯而易見的。這次的列表數(shù)據(jù)規(guī)模還不算大,后續(xù)如果規(guī)模增加到很大,那么對比將會更加明顯。

2.setHasFixedSize(boolean)的使用

方法的名字就表明了,設(shè)置是否有固定的尺寸,就是說RecyclerView是否有固定的尺寸,如果設(shè)置了true。那么會在以下的情景用到:

onMeasure---測量

如果設(shè)置了true,那么RecyclerView的mHasFixedSize變量為true。

@Override
    protected void onMeasure(int widthSpec, int heightSpec) {
      if (mLayout == null) {
            defaultOnMeasure(widthSpec, heightSpec);
            return;
        }
      //是否允許自動測量
      if (mLayout.isAutoMeasureEnabled()) {
        .....
      } else {
        if (mHasFixedSize) { //是否有固定的尺寸
                mLayout.onMeasure(mRecycler, mState, widthSpec, heightSpec);
                return;
            }
        .........
      }
    }
 
// mLayout.onMeasure
 public void onMeasure(@NonNull Recycler recycler, @NonNull State state, int widthSpec,
                int heightSpec) {
            mRecyclerView.defaultOnMeasure(widthSpec, heightSpec);
        }
 
 void defaultOnMeasure(int widthSpec, int heightSpec) {
               //直接設(shè)置固定的寬度和高度,沒有進(jìn)行再次的測量
        final int width = LayoutManager.chooseSize(widthSpec,
                getPaddingLeft() + getPaddingRight(),
                ViewCompat.getMinimumWidth(this));
        final int height = LayoutManager.chooseSize(heightSpec,
                getPaddingTop() + getPaddingBottom(),
                ViewCompat.getMinimumHeight(this));
 
        setMeasuredDimension(width, height);
    }

所以設(shè)置了這個值的時候,RecyclerView在測量的時候會有性能上的提升。

3.setHasStableIds(boolean)的使用

方法的名稱意思是設(shè)置是否有穩(wěn)定的id,設(shè)置了該值為true后,ViewHolder中的mHasStableIds就為true。

StableId有三種模式:NO_STABLE_IDS、ISOLATED_STABLE_IDS、SHARED_STABLE_IDS

RecyclerView在進(jìn)行Item的Remove,Insert,Change的時候會調(diào)用到。

如果設(shè)置了這個屬性,那么需要在Adapter中重寫getItemId(int position)方法。

這樣子在進(jìn)行列表的更新時候,Adapter會根據(jù)getItemId方法返回的long類型的id進(jìn)行判斷,決定當(dāng)前的item是否需要刷新。因此取代以往的全部刷新的情況,從而提高效率。

 
class Album{
     String coverUrl;
     String title;
}
 
@Override
public long getItemId(int position){
    Album album = mListOfAlbums.get(position);
      //如果返回的id和上次不一樣,那就代表這個item發(fā)生了數(shù)據(jù)變化,則進(jìn)行刷新
      //如果返回的id和上次一致,那么這個item就沒有改變,就無需刷新了。
    return (album.coverUrl + album.title).hashcode();
}

4.ViewCacheExtension的使用

它是一個靜態(tài)抽象類,看類名就能大概知道view緩存擴(kuò)展,類中包括方法:

/**
        返回一個能綁定到適配器position位置上的view 
         * <p>
         * 此方法不應(yīng)該創(chuàng)建新的視圖。 相反,它期望返回一個已經(jīng)創(chuàng)建的View,該View可以針對給定的類型和位置重                        新使用。 如果將視圖標(biāo)記為已忽略,則應(yīng)先調(diào)用{@link LayoutManager#
              stopIgnoringView(View)},然后再返回視圖。
         * RecyclerView將在必要時將返回的View重新綁定到該位置
         *
         * @param recycler The Recycler that can be used to bind the View
         * @param position The adapter position
         * @param type     The type of the View, defined by adapter
         * @return 綁定到給定位置的View;如果沒有可重用的View,則為NULL
         * @see LayoutManager#ignoreView(View)
         */
public abstract View getViewForPositionAndType(@NonNull Recycler recycler, int position,
                int type);

該緩存為RecyclerView的第二級緩存,即如果開發(fā)者設(shè)置了該緩存,那么列表從CacheView中獲取不到holder,就會從ViewCacheExtension從獲取。

適用場景則為,列表有固定的數(shù)量條目和寬高,這樣子,列表初始化的時候就能直接從這級緩存拿到ViewHolder,不需要再創(chuàng)建ViewHolder,大大節(jié)省時間,提高效率。

5.預(yù)加載

預(yù)加載功能在RecyclerView中是默認(rèn)開啟的。

public boolean onTouchEvent(MotionEvent e) {
   switch (action) {
       case MotionEvent.ACTION_MOVE: {
                      final int x = (int) (e.getX(index) + 0.5f);
                final int y = (int) (e.getY(index) + 0.5f);
                int dx = mLastTouchX - x;
                int dy = mLastTouchY - y;
                         if (mScrollState == SCROLL_STATE_DRAGGING) { //處于拖動狀態(tài)
                    ........
                    if (mGapWorker != null && (dx != 0 || dy != 0)) { //滑動距離不等于0,
                        mGapWorker.postFromTraversal(this, dx, dy); //進(jìn)行預(yù)取任務(wù)
                    }
                }
       }
       break;
   }
}
 
        /**
     * 在當(dāng)前遍歷之后立即安排預(yù)取。
     */
    void postFromTraversal(RecyclerView recyclerView, int prefetchDx, int prefetchDy) {
        if (recyclerView.isAttachedToWindow()) {
            ........
            //第一次觸發(fā)拖動的是否將該runnable提交到Mainhandler里面,
            //等待UI thread執(zhí)行完成再執(zhí)行預(yù)取任務(wù) 
            if (mPostTimeNs == 0) {
                mPostTimeNs = recyclerView.getNanoTime();//獲取當(dāng)前時間,記錄改次任務(wù)的開始
                recyclerView.post(this); //提交當(dāng)前任務(wù)
            }
        }
                //設(shè)置預(yù)加載的坐標(biāo)
        recyclerView.mPrefetchRegistry.setPrefetchVector(prefetchDx, prefetchDy);
    }
 
         /**
     * 獲取當(dāng)前系統(tǒng)的時間,單位為納秒
     */
        long getNanoTime() {
        if (ALLOW_THREAD_GAP_WORK) { //在Android5.0及以上的系統(tǒng)中
            return System.nanoTime(); //返回正在運(yùn)行的Java虛擬機(jī)的高分辨率時間源的當(dāng)前值,以納秒為單位
        } else {
            return 0; //5.0以下的系統(tǒng)直接返回0
        }
    }
 
 
        /**
        在L +上,使用RenderThread,UI線程在將一幀傳遞給RenderThread之后但在下一幀開始之前具有空閑時間。我們        在此窗口中安排預(yù)取工作。
     */
    static final boolean ALLOW_THREAD_GAP_WORK = Build.VERSION.SDK_INT >= 21;

我們可以看下預(yù)加載程序的Runnable的run方法實(shí)現(xiàn)了什么操作。

@Override
    public void run() {
        try {
            TraceCompat.beginSection(RecyclerView.TRACE_PREFETCH_TAG);
                        //recyclerview嵌套的情況
            if (mRecyclerViews.isEmpty()) {
                // abort - no work to do
                return;
            }
 
                 //查詢最新的vsync,以便于我們預(yù)測下一個
              //繪制時間在動畫和輸入的回調(diào)中未生效,所以在這里進(jìn)行vsync的查詢是安全的
            final int size = mRecyclerViews.size();
            long latestFrameVsyncMs = 0;
               //獲取RecyclerView最近一次開始RenderThread的時間
            for (int i = 0; i < size; i++) {
                RecyclerView view = mRecyclerViews.get(i);
                if (view.getWindowVisibility() == View.VISIBLE) {
                    latestFrameVsyncMs = Math.max(view.getDrawingTime(), latestFrameVsyncMs);
                }
            }
 
            if (latestFrameVsyncMs == 0) {
                //終止,沒有任何視圖可見,或者無法獲得最新的vsync用于估計(jì)下一個
                return;
            }
                        //計(jì)算下一幀的時間,等于最新一幀的時間加上幀間隔的時間
              //事實(shí)上,這是預(yù)加載工作的最后期限時間,如果不能在這個時間之前完成,那就意味著預(yù)加載失敗
            long nextFrameNs = TimeUnit.MILLISECONDS.toNanos(latestFrameVsyncMs) + mFrameIntervalNs;
                        //進(jìn)行預(yù)加載
            prefetch(nextFrameNs);
 
            // TODO: consider rescheduling self, if there's more work to do
        } finally {
            mPostTimeNs = 0;
            TraceCompat.endSection();
        }
    }
void prefetch(long deadlineNs) {
              //建立任務(wù)列表
        buildTaskList();
              //在deadlineNs這個時間前執(zhí)行并完成任務(wù)
        flushTasksWithDeadline(deadlineNs);
    }
 
private void flushTasksWithDeadline(long deadlineNs) {
        for (int i = 0; i < mTasks.size(); i++) {
            final Task task = mTasks.get(i);
            if (task.view == null) {
                break; // done with populated tasks
            }
            flushTaskWithDeadline(task, deadlineNs);
            task.clear();
        }
    }

6.更新列表的方式

item局部更新

單項(xiàng)item更新

notifyItemChanged(position)

notifyItemInserted(position)

notifyItemRemoved(position)

notifyItemMoved(fromPosition, toPosition)

整體列表更新

notifyDataSetChanged(慎用)

notifyItemRangeRemoved(positionStart, itemCount)

notifyItemRangeChanged(positionStart, itemCount)

notifyItemRangeInserted(positionStart, itemCount)

其它的優(yōu)化點(diǎn)

過度繪制

如果列表中的一個Item存在過度繪制,那么列表所有的item都過度繪制,就到存在不必要的渲染工作,消耗系統(tǒng)資源。

防止過度繪制,可以打開開發(fā)者選項(xiàng)中的《調(diào)試GPU過度繪制》,查看頁面中的顏色分區(qū),然后進(jìn)行對應(yīng)的優(yōu)化。

Android 將按如下方式為界面元素著色,以確定過度繪制的次數(shù):

真彩色:沒有過度繪制

藍(lán)色:過度繪制 1 次

綠色:過度繪制 2 次

粉色:過度繪制 3 次

紅色:過度繪制 4 次或更多次

因?yàn)樵诓季种型粠啻卫L制相同的像素就會發(fā)生繪制過度,因此修復(fù)過度繪制可以減少不必要的渲染工作,以此來提高性能。特別是對于大型,多列表的布局來說。

總結(jié)

到此這篇關(guān)于android RecyclerView的一些優(yōu)化點(diǎn)介紹的文章就介紹到這了,更多相關(guān)android RecyclerView內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Android實(shí)現(xiàn)截圖分享qq 微信功能

    Android實(shí)現(xiàn)截圖分享qq 微信功能

    在日常生活中,經(jīng)常用到qq,微信截圖分享功能,今天小編通過本文給大家介紹Android實(shí)現(xiàn)截圖分享qq 微信功能,具體實(shí)現(xiàn)代碼大家參考下本文
    2017-12-12
  • 淺談Android Studio 解析XML的三種方法

    淺談Android Studio 解析XML的三種方法

    這篇文章主要介紹了淺談Android Studio 解析XML的三種方法,Android Studio 解析XML常見的三種方式:DOM PULL SAX,非常具有實(shí)用價值,需要的朋友可以參考下
    2018-07-07
  • 淺談Android硬件加速原理與實(shí)現(xiàn)簡介

    淺談Android硬件加速原理與實(shí)現(xiàn)簡介

    這篇文章主要介紹了淺談Android硬件加速原理與實(shí)現(xiàn)簡介,本文嘗試從底層硬件原理,一直到上層代碼實(shí)現(xiàn),對硬件加速技術(shù)進(jìn)行簡單介紹,感興趣的小伙伴們可以參考一下
    2018-07-07
  • Kotlin淺析延遲初始化與密封類的實(shí)現(xiàn)方法

    Kotlin淺析延遲初始化與密封類的實(shí)現(xiàn)方法

    Kotlin語言的許多特性,包括變量不可變,變量不可為空,等等。這些特性都是為了盡可能地保證程序安全而設(shè)計(jì)的,但是有些時候這些特性也會在編碼時給我們帶來不少的麻煩,下面我們來了解延遲初始化和密封類的特點(diǎn)
    2022-08-08
  • Android系統(tǒng)的五種數(shù)據(jù)存儲形式實(shí)例(一)

    Android系統(tǒng)的五種數(shù)據(jù)存儲形式實(shí)例(一)

    Android系統(tǒng)有五種數(shù)據(jù)存儲形式,分別是文件存儲、SP存儲、數(shù)據(jù)庫存儲、contentprovider 內(nèi)容提供者、網(wǎng)絡(luò)存儲。本篇文章詳解的介紹了每種數(shù)據(jù)存儲的用法,有興趣的可以了解一下。
    2016-12-12
  • Android編程實(shí)現(xiàn)調(diào)用相冊、相機(jī)及拍照后直接裁剪的方法

    Android編程實(shí)現(xiàn)調(diào)用相冊、相機(jī)及拍照后直接裁剪的方法

    這篇文章主要介紹了Android編程實(shí)現(xiàn)調(diào)用相冊、相機(jī)及拍照后直接裁剪的方法,涉及Android拍照及圖形處理相關(guān)操作技巧,需要的朋友可以參考下
    2017-02-02
  • 基于Android實(shí)現(xiàn)顏色漸變動畫效果

    基于Android實(shí)現(xiàn)顏色漸變動畫效果

    本文主要給大家介紹了Android實(shí)現(xiàn)顏色漸變動畫效果,實(shí)現(xiàn)這樣的一個動畫漸變的效果很簡單,只需要兩步,第一步用GradientDrawable實(shí)現(xiàn)兩個顏色之間的漸變效果,第二步用屬性動畫實(shí)現(xiàn)顏色變化的過程,需要的朋友可以參考下
    2024-01-01
  • 基于TransactionTooLargeException異常分析

    基于TransactionTooLargeException異常分析

    下面小編就為大家分享一篇基于TransactionTooLargeException異常分析,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2017-11-11
  • Android?SeekBar充當(dāng)Progress實(shí)現(xiàn)兔兔進(jìn)度條Plus

    Android?SeekBar充當(dāng)Progress實(shí)現(xiàn)兔兔進(jìn)度條Plus

    這篇文章主要為大家介紹了Android?SeekBar充當(dāng)Progress實(shí)現(xiàn)兔兔進(jìn)度條Plus示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-02-02
  • 一文講解Kotlin中的contract到底有什么用

    一文講解Kotlin中的contract到底有什么用

    我們在開發(fā)中肯定會經(jīng)常用Kotlin提供的一些通用拓展函數(shù),當(dāng)我們進(jìn)去看源碼的時候會發(fā)現(xiàn)許多函數(shù)里面有contract{}包裹的代碼塊,那么這些代碼塊到底有什么作用呢?下面這篇文章主要給大家介紹了關(guān)于Kotlin中contract到底有什么用的相關(guān)資料,需要的朋友可以參考下
    2022-01-01

最新評論

日照市| 霍林郭勒市| 铁力市| 万源市| 景洪市| 墨江| 上犹县| 怀集县| 弥渡县| 通河县| 威远县| 长武县| 满城县| 龙江县| 罗甸县| 石嘴山市| 宁安市| 凯里市| 界首市| 大城县| 丰原市| 扶沟县| 安平县| 灌云县| 乌鲁木齐市| 古田县| 五寨县| 武平县| 清水县| 磐石市| 诸城市| 永胜县| 三都| 通城县| 克拉玛依市| 丽江市| 南通市| 濉溪县| 全州县| 英德市| 贵南县|