日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

RecyclerView 数据预取

發布時間:2025/3/17 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 RecyclerView 数据预取 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
本文講的是RecyclerView 數據預取,

更快處理任務,使滾動和滑動更流暢

在我小時候,媽媽為了治療我的拖延癥,總是告訴我:“如果你現在打掃你的房間,就不用以后再打掃了。”但我從沒這樣做。我知道最好能拖延就盡量拖延。一個原因是:如果我現在打掃了,房間還會變臟,那時候我就必須再打掃一遍了。另外,如果我把這件事放下足夠久,媽媽可能會忘了它的。

拖延對我來說總是有效。但我永遠不用處理保持幀率的問題,不像我的朋友 RecyclerView 一樣。

問題

在一次滾動或慣性滑動中,RecyclerView 需要在新條目抵達屏幕時予以展示。這些新條目需要與數據相綁定(如果緩存中沒有相應條目的話,還需要創建一個)。接下來,它們還需要被展開并畫出來。如果所有這些都是被懶加載的,在需要展示之前才做,UI 線程就會在工作完成時陷入停頓。接下來渲染可以繼續并且滾動(或者說滑動,但我打算用滾動來指代它們,以簡化討論)可以平滑地繼續,直到下一個條目進入視野范圍。

一次典型的 RecyclerView 內容滾動中的各個渲染階段(在?Lollipop?版本時的情況)。在UI線程,我們處理輸入事件和動畫,完成布局,并且記錄繪圖操作。接下來渲染線程把指令送往GPU。 在一次滾動的大多數幀中,RecyclerView 可以沒問題地完成它需要做的事,因為不需要處理新的內容。在這些幀中,UI 線程處理輸入事件和動畫,完成布局,記錄繪圖操作。接下來它把繪圖信息與渲染線程同步(在 Lollipop 版本時的情況,之前的版本在 UI 線程完成所有工作),渲染線程把指令送往 GPU。

新條目使得輸入階段耗時更長,因為新的 view 需要被創建、綁定并布局。這推遲了渲染階段的開始,從而導致它可能在幀的邊界之后結束。在此情況下,就會發生掉幀。當一個新的條目來到屏幕中時,輸入階段就需要完成更多工作,以綁定(可能還要創建)正確的 view。這推遲了 UI 線程其余的工作,以及渲染線程接下來的工作。如果這些不能在幀邊界內完成的話,就會發生卡頓。

輸入階段的調用棧表明:新的條目進入視野范圍會導致一大塊時間被用于創建和綁定新的 view。 如果我們可以在其它地方完成這些工作,而不推遲所有其它事情,不就很好嗎??

在 view 可以被渲染之前,創建和綁定必須完成。這會在相應的幀中消耗 UI 線程的寶貴時間。然而,UI 線程在前一幀中有大量時間無所事事。?Chris Craik(Android UI Toolkit 組的工程師)在用?Systraces?查看 RecyclerView 滾動時發現了這一點。他特別注意到,我們在需要使用一個條目時,會花費大量時間準備它。而在一幀之前,UI 線程花了大量時間休眠,因為它很早就完成了任務。

解決方案

將創建和綁定工作移到前一幀,使 UI 線程能夠與渲染線程同時工作,從而避免接下來在渲染線程繪制結果之前同步完成這些工作。 顯然,這是優化耗時的好時機。Chris 重新安排了默認 RecyclerView 布局時事件發生的順序,它現在在一個條目即將進入視野時預取數據,這樣我們可以在空閑期完成工作,避免拖到大家都在等待結果時才完成。 完成這些工作基本上沒有任何代價,因為 UI 線程在兩幀之間的空隙不做任何工作。我們可以使用這些空閑時間來完成將來的工作,并使得未來的幀出現得更快,因為困難的部分已經被完成了。

細節,細節

這個系統的工作方式是,在 RecyclerView 開始一個滾動時安排一個 Runnable。這個 Runnable 負責根據 layout manager 和滾動的方向預取即將進入視野的條目。預取不限于一個單獨的條目。它可以同時取出多個條目,例如在使用 GridLayoutManager 且新的一行馬上要出現的時候。在 25.1 版本中,預取操作被分為單獨的創建/綁定操作,從而比對整組條目做操作更容易被納入 UI 線程的空隙中。

有趣的是,系統必須預測操作需要多少時間,以及它們是否可以被放入空隙中。畢竟,如果預取把當前幀推遲到截止時間之后,我們仍然會因掉幀而感覺到卡頓,只是和不預取時原因不同而已。系統處理這些細節的方式是追蹤每種 view 類型的平均創建/綁定時間,從而使未來創建/綁定時間的合理預測成為可能。

對嵌套 RecyclerView(每一個條目自身都是 RecyclerView 的容器)完成這些工作更加復雜,因為綁定內部 RecyclerView 并不涉及任何子控件的分配——RecyclerView 在被綁定和布局時按需取得子控件。預取系統仍然可以預先準備內層的 RecyclerView 內部的子控件,但它必須知道有多少。這就是 25.1 版本中 LinearLayoutManager 新 API?setInitialItemPrefetchCount()的意義。它告訴系統,在滾動時需要預取多少條目來充滿 RecyclerView。

警告

你需要注意這些危險:

-預取數據可能做一些最終不被需要的工作。因為我們在預取 view 時,有可能會采取太激進的策略,這樣 RecyclerView 就可能不會滾動到我們預取的條目。這意味著我們的預取工作可能會被浪費(雖然這些工作是被并行完成的,應該不會浪費太多時間。另外,浪費是不太可能發生的,因為我們在需要數據之前不久才去預取,而且滾動不太可能在兩幀之間停止或反轉)。 -渲染線程:渲染線程是 Lollipop 版本引入的性能特性,它可以讓一個不同的線程分擔渲染工作,并且支持其他的一些改進,例如把不可變的動畫(如漣漪、環形展現等)完全放在渲染線程,使其不受 UI 線程停頓的影響。這意味著運行 Lollipop 之前的版本的設備將不會受益于這個優化,因為我們無法并行完成這些工作。

我要一些 —— 去哪兒拿?

預取優化是在?Support Library v25中引入,在?v25.1.0中改進的。所以第一步是下載?最新版本的支持庫。

如果你使用 RecyclerView 提供的默認 layout manager,你將自動獲得這種優化。然而,如果你使用嵌套 RecyclerView 或者自己寫 layout manager,你需要改變你的代碼來利用這個特性。

對于嵌套 RecyclerView 而言,要獲取最佳的性能,在內部的 LayoutManager 中調用 LinearLayoutManager 的setInitialItemPrefetchCount()方法(25.1版本起可用)。例如,如果你豎直方向的list至少展示三個條目,調用 setInitialItemPrefetchCount(4)。

如果你實現了自己的 LayoutManager,你需要重寫?LayoutManager.collectAdjacentPrefetchPositions()方法。該方法在數據預取開啟時被 RecyclerView 調用(LayoutManager 的默認實現什么都不做)。第二,在嵌套的內層 RecyclerView 中,如果你想讓你的 LayoutManager 預取數據,你同樣應當實現?LayoutManager.collectInitialPrefetchPositions()。

和以前一樣,優化你的創建和綁定步驟,做盡可能少的工作,是值得的。運行的最快的代碼是根本不需要運行的代碼;即使框架可以通過數據預取并行工作,它仍然消耗時間,而且耗時較長的條目創建仍然可以導致卡頓。例如,一棵最小的 view 樹總比一棵復雜的更容易創建和綁定。本質上,綁定應該和調用 setter 一樣方便,一樣快。即使你用目前的代碼就可以在一幀的時間限制中完成工作,進一步優化意味著它將更可能在低端的用戶機型上運行良好。此外,在高端設備上為這些常用場景節約性能,總是對電池有益的。如果你已經盡可能縮短了創建和綁定的時間,預取將會幫助你縮短兩幀之間的剩余時間。

如果你想要見到實際的優化,在默認或自定義的 LayoutManager 中,你可以切換?LayoutManager.setItemPrefetchEnabled()并比較結果。你應該能夠從視覺上直觀地看到差異;它確實如此顯著,特別是在條目需要大量時間創建和綁定的情況下。但如果你想知道在表面下發生過什么,在預取打開和關閉時運行Systrace, 或者打開?GPU profiling。

Systrace 顯示數據預取在UI線程空閑時預取數據。

GOTO 結尾

查看?最新的 Support Library并和能預取數據的 RecyclerView 一起玩耍。同時,我將繼續不清理我的房間。






原文發布時間為:2017年2月14日
本文來自云棲社區合作伙伴掘金,了解相關信息可以關注掘金網站。

總結

以上是生活随笔為你收集整理的RecyclerView 数据预取的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。