Android介面卡頓

2021-07-24 19:00:44 字數 2920 閱讀 9790

前段時間在開發專案時搞了一下過渡繪製的問題,乙個比較複雜的介面剛開發出來,過渡繪製95%紅,調了半天後,基本只有5%的紅,效果不錯,準備找個時間總結一下,今天剛好看到網上以為大神發了一篇文章,總結的不錯,順手牽過來啦,哈哈哈~

使用者對卡頓的感知, 主要**於介面的重新整理. 而介面的效能主要是依賴於裝置的ui渲染效能. 如果我們的ui設計過於複雜, 或是實現不夠好, 裝置又不給力, 介面就會像卡住了一樣, 給使用者卡頓的感覺.

在剖析卡頓的原因之前, 我們先來了解下android中著名的」16ms」原則:

例如, 假設我們更新螢幕的背景, 需要24ms來做這次運算. 當系統在第乙個16ms時重新整理介面, 然而我們的運算還沒有結束, 無法繪出. 當系統隔16ms再發一次vsync資訊重繪介面時, 使用者才會看到更新後的. 也就是說使用者是32ms後看到了這次重新整理(注意, 並不是24ms). 這就是傳說中的丟幀(dropped frame):

丟幀給使用者的感覺就是卡頓, 而且如果運算過於複雜, 丟幀會更多, 導致介面常常處於停滯狀態, 卡到爆.

那麼會有哪些常見的情況會導致運算超過16ms, 進而丟幀, 讓使用者覺得卡頓呢?

一般來說, 會有以下幾種情況導致卡頓這種效能問題, 我們逐一看下:

上節有說, 介面效能取決於ui渲染效能. 我們可以理解為ui渲染的整個過程是由cpu和gpu兩個部分協同完成的.

其中, cpu負責ui布局元素的measure, layout, draw等相關運算執行. gpu負責柵格化(rasterization), 將ui元素繪製到螢幕上.

如果我們的ui布局層次太深, 或是自定義控制項的ondraw中有複雜運算, cpu的相關運算就可能大於16ms, 導致卡頓.

這個時候, 我們需要借助hierarchy viewer這個工具來幫我們分析布局了. hierarchy viewer不僅可以以圖形化樹狀結構的形式展示出ui層級, 還對每個節點給出了三個小圓點, 以指示該元素measure, layout, draw的耗時及效能.

上節說的cpu方面的, 關於gpu的繪製, 如果我們的介面存在overdraw, 也可能導致卡頓.

overdraw: 用來描述乙個畫素在螢幕上多少次被重繪在一幀上.

通俗的說: 理想情況下, 每屏每幀上, 每個畫素點應該只被繪製一次, 如果有多次繪製, 就是overdraw, 過度繪製了.

android系統提供了視覺化的方案來讓我們很方便的檢視overdraw的現象:

在」系統設定」–>」開發者選項」–>」除錯gpu過度繪製」中開啟除錯:

此時介面可能會有五種顏色標識:

上面有言, 所謂overdraw, 就是在乙個畫素點上繪製了多次. 常見的就是:

繪製了多重背景.

繪製了不可見的ui元素.

開啟應用, 展示是這樣的:

可以看到是中間列表這塊overdraw比較嚴重. 檢視**發現:

fragment_trending_container.xml中viewpager設定了背景:

.support

.v4.view

.viewpager

android:id="@+id/view_pager"

android:background="@color/md_white_1000"

android:layout_width="match_parent"

android:layout_height="match_parent"/>

而viewpager中的fragment又設定了背景:

<?xml version="1.0" encoding="utf-8"?>

""android:id="@+id/refresh_layout"

android:background="@color/md_white_1000"

android:layout_width="match_parent"

android:layout_height="match_parent">

...刪除外層viewpager的背景再看:

可以發現中間列表區域已經不再是紅色了, 但是也沒有達到藍色這個可以接受的層級. 這是因為我們的activity預設情況下, theme會給window設定乙個純色的背景. 因為我們這裡不想使用這個預設的背景,故而給layout加了一層背景, 導致了多重繪製背景.

(當然我們也可以自定義主題, 將theme的window background設定成我們想要的, 而不在布局中設定.)

可以通過如下方式去掉window的背景.

設定主題:

@null

item>

或是**設定, 在oncreate中:

getwindow().setbackgrounddrawable(null);
此時我們看到的效果:

已基本達到優化水平.

strictmode用來基於執行緒或vm設定一些策略, 一旦檢測到策略違例, 控制台將輸出一些警告,包含乙個trace資訊展示你的應用在何處出現問題.

通常用來檢測主線程中的磁碟讀寫或網路訪問等耗時操作.

public void oncreate() 

super.oncreate();

}

2.4 頻繁的gc

上面說的都是處理上的, cpu, gpu相關的. 實際上記憶體原因也可能會造成應用不流暢, 卡頓的.

簡而言之, 就是執行gc操作的時候,任何執行緒的任何操作都會需要暫停,等待gc操作完成之後,其他操作才能夠繼續執行, 故而如果程式頻繁gc, 自然會導致介面卡頓.

導致頻繁gc有兩個原因:

這些gc操作可能會造成上面說到的丟幀, 如下:

一般來說瞬間大量產生物件一般是因為我們在**的迴圈中new物件, 或是在ondraw中建立物件,或者是在listview的getview中建立物件等. 所以說這些地方是我們尤其需要注意的…

介面卡頓優化

在螢幕上乙個畫素點出現多次繪製 如背景重疊繪製 優化做法 在繪製時例項化物件 ondraw 手機不能進入休眠狀態 資源忘記 handler使用不當導致記憶體洩漏 無用的屬性和資源 可優化的布局 沒有使用sparsearray代替hashmap 主線程中占用cpu時間過長的函式,特別關注io操作 檔案...

android學習 陣列介面卡 簡單介面卡

資料介面卡是將複雜的資料來源填充到指定的檢視介面中 1 陣列介面卡arrayadapter 用於繫結型別單一的資料,資料 可以是陣列或集合 2 簡單介面卡 adapter 也叫 並不簡單的簡單介面卡 用於繫結格式複雜的資料,資料 只能是特定泛型的集合 作用 介面卡是連線資料來源和檢視介面的橋梁 介面...

Android介面卡BaseAdapter詳解

次元立方 程式設計資料庫 安全設計 網頁系統 伺服器組網 嵌入式基礎 name loginwin id loginwin src allowtransparency true height 30 frameborder 0 scrolling no width 100 marginwidth 0 m...