Android效能優化(4):UI渲染機制以及優化
文章目錄
在從Android 6.0原始碼的角度剖析View的繪製原理一文中,我們瞭解到View的繪製流程有三個步驟,即measure(
測量
)、layout(佈局
)和draw(繪製
),它們主要執行在系統應用框架層,而真正將資料渲染到螢幕上的則是系統Native層的SurfaceFlinger服務
來完成的。本文將暫不對SurfaceFlinger服務
的執行流程進行剖析,而是從更加底層的角度來了解APP的渲染機制,同時引出在渲染過程中遇到的效能問題,以及如何去發現、優化它們。
1. 渲染機制分析
1.1 渲染機制
對於開發者來說,APP的介面主要是由XML佈局檔案
來表現的,每個XML佈局檔案
中又包括了很多檢視元件,比如ImageView、Button、TextView等等,它們分別表示了圖片、按鈕、字串等不同的資訊,那麼這些複雜的XML佈局檔案和標記語言,又是如何轉化成為使用者能夠看得懂的影象的呢?答案是:格柵化(Rasterization)
!所謂格柵化,就是將例如字串
、按鈕
、路徑
或者形狀
等的一些高階物件,拆分到不同的畫素螢幕上進行顯示。格柵化是一個非常費時的操作,CPU作為中央處理器本身任務就比較繁重,因此人們引入了GPU(影象處理器)
這塊特殊的硬體來加快格柵化操作(硬體加速)。格柵化操作大體如下:
接下來,我們就來詳細瞭解XML佈局檔案中的UI元件是如何被格柵化並渲染顯示在螢幕上的?在APP繪製渲染過程中,與繪製渲染有關的硬體主要有CPU和GPU(圖形處理器),其中,CPU負責把UI元件計算成Polygons(多邊形)
或Texture(紋理)
,而CPU負責格柵化和渲染工作。CPU和GPU通過圖形驅動層
進行連線,這個圖形驅動層
維護了一個Display List
佇列,它們分別充當生產者
和消費者
,協作完成具體的繪製渲染過程。繪製渲染過程如下圖所示:
- 渲染流程如下:
首先
,CPU
會對UI元件(View)進行Measure
、Layout
、Record
、Execute
的資料計算工作,以將其計算成的Polygons(多邊形)
或Texture(紋理)
,它們是GPU能夠識別的物件,而承載這些資訊的是一個被稱為Display List
的結構體,它持有所有交給GPU繪製到螢幕上的資料資訊,包含GPU要繪製的全部物件的資訊列表和執行繪製操作的OpenGL命令列表。在某個View第一次需要被渲染的時候,Display List
會因此被建立,當這個View需要顯示到螢幕上時,GPU接收到繪製指令後會執行該Display List
。每個View擁有自己的Display List
,Display Lis
本身也構成一個樹狀的結構,跟View Hierachy(檢視樹)
保持一致。
其次
,由於每次從CPU計算得到的Polygons
或Texture
提交(轉移)GPU是一件比較麻煩且耗時的事情(注:實際提交的是Display List
),因此Android系統又引入了OpenGL ES,該庫API允許將那些需要渲染的Polygons
或Texture
儲存(Hold)在GPU儲存器(視訊記憶體)中,當下一次需要渲染的時候只需要在GPU儲存器裡引用它,然後告訴OpenGL如何繪製就可以了,而不再需要經過CPU上傳。需要注意的是,假如View的繪製內容發生變化,那麼GPU Memory儲存的Display List
就無法再繼續使用,這時就需要CPU重新計算建立Display List
並重新執行指令更新到螢幕。
最後,當GPU完成對紋理的格柵化、渲染後,它會將渲染的結果放入幀緩衝區
,視訊控制器會按照VSync(垂直同步)
訊號逐行讀取幀緩衝區的資料,經過可能的數模轉換傳遞給顯示器顯示。
- CPU、OpenGL與GPU之間的關係
1.2 卡頓現象
前面說到,當GPU渲染完成後會將渲染的結果儲存到幀緩衝區
,視訊控制器會按照VSync(垂直同步)
訊號逐行讀取幀緩衝區的資料,經過可能的數模轉換傳遞給顯示器顯示。那麼問題來了,什麼是VSYNC訊號?在講解VSYNC之前,我們需要了解兩個相關的概念:Refresh Rate
和Frame Rate
。
Refresh Rate(重新整理頻率)
表示螢幕在一秒內被重新整理的次數,取決於硬體的固定引數,目前大部分手機這個固定引數(螢幕重新整理頻率)為60Hz
。也就是說,Android系統每隔約16ms(1000ms/60=16.66ms)
就會重新重新整理一次介面(Activity),因此我們有16ms的時間去完成每幀的繪製、渲染的邏輯操作。
Frame Rate(幀率)
表示GPU在一秒內能夠渲染的幀數,通常為60fps
。為什麼是60fps
?這是因為人眼與大腦之間的協作無法感知超過60fps
的畫面更新。簡單的說,人眼看到的動畫其實都是一幀幀連續播放的靜態圖片,當播放的速度達到1秒針24幀(24fps
)時,對於人眼感知來說就是連續的線性運動。當然低於30fps在某些場景仍然無法順暢表現絢麗的畫面,此時就需要60fps
來達到想要的效果。
現在我們再來理解下VSYNC訊號:**螢幕的重新整理過程是每一行從左到右(水平重新整理,Horizontal Scanning
),從上到下(垂直重新整理,Verical Scanning)。當整個螢幕重新整理完畢,即一個垂直重新整理週期完成,會有短暫的空白期,此時Android系統就會發出VSYNC訊號,觸發下一幀對UI的渲染、顯示。VSYNC是一種定時中斷,一旦收到VSYNC訊號CPU就開始處理幀資料,通常Android系統每隔16ms發出VSYNC訊號,這個週期時間由螢幕重新整理頻率決定。**通常來說,幀率超過重新整理頻率只是一種理想的狀態,在超過60fps
的情況下,GPU所產生的幀資料會因為等待VSYNC
的重新整理資訊而被Hold住,這樣能夠保持每次螢幕重新整理都有實際的新的資料可以顯示。但是基本上我們遇到的是幀率<=螢幕重新整理頻率
的情況,尤其是在幀率小於重新整理頻率時,會出現待VSYNC
訊號到來時,螢幕沒有可以重新整理的資料,即幀緩衝區還是之前的那幀影象,這就會導致螢幕顯示的該幀畫面內容仍然是上一幀的畫面,而這種現象我們就稱之為"掉幀
",對於使用者來說,就是介面出現了卡頓現象
,即執行不流暢。
由此我們可以得出,Android系統之所以會出現卡頓現象
是因為的某些操作耗費了幀間隔時間(16ms
),導致其他類似計算、渲染等操作的可用時間就會變少,在16ms
無法完成正常的繪製、渲染工作。當下一個VSYNC訊號到來時,Android系統嘗試在螢幕上繪製新的一幀,但是新的一幀還沒準備好,就會導致無法進行正常渲染,畫面就不會重新整理,使用者看到的還是上一幀的畫面,從而發生了丟幀。產生卡頓的原因有很多,主要有以下幾點:
佈局Layout過於複雜,無法在16ms內完成渲染;
同一時間動畫執行的次數過多,導致CPU或GPU負載過重;
View過度繪製,導致某些畫素在同一幀時間內被繪製多次
在UI執行緒中做了很多耗時的操作;
GC回收時暫停時間過長或者頻繁GC產生大量的暫停時間(記憶體抖動);
1.3 記憶體抖動
在1.2小節我們談到,大量不停的GC操作會顯著佔用幀間隔時間(16ms
),如果在幀間隔時間裡面做了過多的GC操作,那麼自然其他類似計算,渲染等操作的可用時間就變得少了,就容易出現丟幀現象,而導致這種頻繁GC的原因之一就是“記憶體抖動(Memory Churn)
”。記憶體抖動是因為大量的物件被建立又在短時間內馬上被釋放,瞬間產生大量的物件會嚴重佔用年輕代(Yong Generation)
的記憶體區域,當達到閥值時剩餘空間不夠的時候,也會觸發GC。即使每次分配的物件佔用了很少的記憶體,但是他們疊加在一起會增加Heap的壓力,從而觸發更多其他型別的GC。
2. 渲染優化方式
從上一小節的分析可知,Android系統的渲染機制主要體現在CPU的繪製和GPU的格柵化、渲染兩個階段,其中,主要比較耗時的在CPU的繪製過程,即將UI物件轉換為一系列的多邊形和紋理,和從CPU上傳Display List資料到GPU過程。如果CPU/GPU 負載過量或者上傳資料次數過多,就會導致 16ms 內沒有繪製、渲染完成出現渲染效能問題。因此,對於渲染效能方面的的優化,我們將從這兩個方面進行剖析,即減輕CPU/GPU的負載量和減少佔用額外的GPU資源。下面我們就介紹幾個工具來幫助我們發現、解決一些渲染效能優化問題,主要有Profile GPU Rendering
、SysTrace
以及TraceView
等。
2.1 過度繪製優化
所謂過度繪製,指的是在螢幕上某個畫素在同一幀時間內被繪製多次,從而浪費了CPU和GPU的資源
。舉個例子來說,假如我們要粉刷房子的牆壁,一開始刷綠色,接著又開始刷黃色,這樣黃色就將綠色蓋住了,為此第一次的粉刷就白乾了。產生過度繪製主要有兩個原因:
在XML佈局中,控制元件有重疊且都有設定背景
;View的onDraw在同一區域繪製多次;
2.1.1 Show GPU overdraw
Show GPU overdraw
是Android系統提供的一個檢視介面過度繪製
的工具,我們可以在手機設定裡的開發者選項中開啟它,即開發者選項->除錯GPU過度繪製
。Show GPU overdraw效果:
開啟除錯GPU過度繪製後,我們的介面就會出現各種顏色,它們的具體含義如下:
白色
:沒有過度繪製,即每個畫素點在螢幕上只繪製了一次;藍色
:一次過度繪製,即每個畫素點在螢幕上繪製了兩次;綠色
:二次過度繪製,即每個畫素點在螢幕上繪製了三次;粉紅色
:三次過度繪製,即每個畫素點在螢幕上繪製了四次;紅色
:四次以上過度繪製;
為此我們可以得出,一個合格的介面應該以白色和藍色為主,綠色以上的區域不要超過整體的三分之一,總之顏色越淺越好。
2.1.2 Profile GPU Rendering
Profile GPU Rendering是Android4.1系統引入用於展示GPU渲染每幀時各個階段所消耗的時間,以便於我們可以直接觀察到渲染該幀時各個階段的耗時情況,即有沒有超過16ms。
我們可以在手機設定裡開發者選項中開啟它(開發者選項->GPU顯示配置檔案/GPU呈現模式分析->在螢幕上顯示為條形圖
),接著手機螢幕的底部就會出現彩色的柱狀。效果如下圖所示:
圖中綠色橫軸代表幀時間,彩色的柱狀(縱軸)表示某一幀的耗時。綠色的橫線為警戒線,超過這條線則意味著該幀繪製渲染的時間超過了16ms,我們應儘量保證垂直的彩色柱狀圖保持在綠線下面,任何時候一幀超過綠線,我們的app將會丟掉一幀。每一個彩色柱狀圖代表一幀的渲染,越長的垂直柱狀圖表示這一幀需要渲染的時間越長。當APP在執行時,我們會看到手機底部的柱狀圖會從左到右動態地顯示,隨著需要渲染的幀數越來越多,他們回堆積在一起,這樣就可以觀察到這段時間幀率的變化。下圖為柱狀圖中不同顏色代表的意義:
顏色意義解釋:
-
橘色
:代表處理的時間。代表CPU在等待GPU完成工作的時間,如果過高表示GPU很繁忙; -
紅色
:代表執行的時間。Android 的2D渲染器向OpenGL發出命令繪製或重繪display lists 花費的時間,柱子的高度等於所有Display list繪製時間的總和。如果紅色柱狀圖很高,可能由於重新提交檢視而導致,還有複雜的自定義View也會導致紅的柱狀圖變高; -
淺藍色
:向CPU傳輸Bitmap花費的時間,過高代表了載入了大量圖形; -
深藍色
:代表繪製的時間。也就是需要多長時間去建立和更新Dispaly List。過高代表在onDraw中花費過多時間,可能是自定義畫圖操作太多或執行了其它操作; -
淡綠色
:代表了onLayout和onMeasure方法消耗的總時間,這段很高代表遍歷整個view樹結構花費了太多時間; -
綠色
:代表為該幀內所有animator求值(屬性動畫中代表通過估值器計算屬性的具體值)所花費的時間.如果這部分過高,代表自定義animator效能不佳或者更新view屬性引發了某些意外操作; -
深綠色
:代表app在使用者輸入事件回撥中花費的時間,這部分過高可能意味著app處理使用者輸入事件時間過長,建議將操作分流到工作執行緒; -
墨綠色
:代表在連續兩幀間的時間間隔,可能是因為子執行緒執行時間過長搶佔了UI執行緒被cpu執行的機會。
為此,我們可以得出在Profile GPU Rendering中,假如紅色/橘色
佔比較大,說明可能出現重複佈局
的情況,可以從否減少檢視層級、減少無用的背景圖、減輕自定義控制元件複雜度
等方面去優化;假如藍色/淺藍/各種綠色
佔比較大,應該從耗時操作
這方面去優化。當然,Profile GPU Rendering可以找到渲染有問題的介面,但是想要修復的話,只依賴Profile GPU Rendering是不夠的,我們可以通過如下兩款工具來定位問題,即TraceView
和Hierarchy Viewer
,前者能夠詳細分析問題原因;後者能夠檢視佈局的層次和每個View所花費的時間。Systrace
總之,我們應儘量從以下幾個方面避免過度繪製。
移除無用的背景圖;
減少檢視層級,儘量使用扁平化佈局,比如Relativeayout;
減輕自定義控制元件複雜度,重疊區域可以使用canvas.clipRect
方法指定繪製區域;`
2.2 卡頓優化
前面我們談到,Android系統之所以會出現卡頓現象
是因為的某些操作耗費了幀間隔時間(16ms
),導致其他類似計算、渲染等操作的可用時間就會變少,在16ms
無法完成正常的繪製、渲染工作。當下一個VSYNC訊號到來時,Android系統嘗試在螢幕上繪製新的一幀,但是新的一幀還沒準備好,就會導致無法進行正常渲染,畫面就不會重新整理,使用者看到的還是上一幀的畫面,從而發生了丟幀,這就是"卡頓現象"。下面我們介紹兩款分析介面卡頓的利器,即SysTrace
和TraceView
,其中,SysTrace
為卡頓原因指明大體方向,TraceView
則是找到是什麼讓CPU繁忙、某些方法的呼叫次數等具體資訊。
2.2.1 SysTrace
SysTrace
是Android 4.1中新增的效能資料取樣和分析工具,它可以幫助我們收集Android關鍵子系統的執行資訊,如SurfaceFlinger、WMS等Framework部分關鍵模組、服務、View體系系統等。Systrace
的功能包括跟蹤系統的I/O操作、核心工作佇列、CPU負載以及Android各個子系統的執行狀態。**對於UI顯示效能,比如動畫播放不流暢、渲染卡頓等問題提供了分析資料。**我們可以在AS的Android Device Monitor(DDMS)開啟Systrace
,需要注意的是,AS 3.0以後谷歌已將DDMS從AS皮膚上移除,但我們仍然可以開啟sdk目錄/tools/monitor.bat
使用它。SysTrace
使用方法如下:
- 具體步驟:
-
雙擊
sdk目錄/tools/monitor.bat
開啟DDMS,單擊DDMS皮膚上的Systrace按鈕; -
進入抓取設定介面後設定跟蹤的時長,以及trace.html檔案輸出路徑等內容;
-
操作APP我們懷疑卡頓的地方,對該過程進行跟蹤;
-
待跟蹤結束後就會在指定路徑生產trace.html檔案,接下來用Chrome瀏覽器開啟它進行分析。
- 用Chrome分析trace.html
總體來說,trace.html主要記錄了Android系統中所有程式和執行緒執行資訊,且同一個程式內按執行緒進行縱向拆分,每個執行緒均記錄了自己的工作。從上圖可知,在trace.html檔案中我們應著重關注三個方面:Alerts
、Frames
和Kernel CPU
,下面我們就詳細分析如何使用它們來定位問題。
- Alerts部分
Alerts部分是Systrace自動分析trace中的事件,並能自動高亮某個效能問題作為一個Alerts(警告),建議除錯人員下一步怎麼做。可以通過點選頂部淺藍色圓圈檢視某一個警告,或者點選右側的Alerts
選項列出所有警告資訊,這些資訊將會按類別列出,比如上圖中列出了Scheduling delay
。選中一條Alert詳情如下:
Scheduling delay
(排程延遲)的意思就是一個執行緒在處理一塊運算的時候,在很長一段時間都沒有被分配到CPU上面做運算,從而導致這個執行緒在很長一段時間都沒有完成工作。從上圖可以看出,選中的這幀只執行了2.343ms
,而有101.459ms
是在休眠,這就意味著這一幀的渲染過程非常慢。當然僅僅通過Alerts的提示仍然無法找到渲染慢的原因,接下來就需要藉助Frames部分進一步定位。
- Frames部分
Frames部分給出的是應該的幀數,每一幀就是一個F圓圈
,F圓圈
有三種顏色:綠色、黃色和紅色,其中,綠色表示該幀渲染流暢(即沒有超過16.66ms,滿足每秒60幀穩定所需的幀),黃色和紅色表示該幀的渲染時間超過了16.66ms,這就意味著黃色和紅色代表的幀存在渲染效能問題(紅色比黃色更嚴重)。我們點選紅色的F圓圈
,在皮膚的底部會給出具體的Alert資訊(同Alert部分),然後我們再按下電腦鍵盤上的M鍵
可以看到被高亮的部分就是這幀精確的時間耗時。應用區域的Frames展示如下:
由於Android 5.0以上系統UI渲染的工作是在UI Thread
和RenderThread
完成的,我們使用鍵盤的W鍵
對這兩個區域放大,然後選擇兩個執行緒中最長的一塊區域(表示某個函式方法)觀察那些View在被填充過程中耗時比較嚴重。我們點選DrawFrame
這個方法,在皮膚的底部可以得到以下資訊:
從上圖可以看出,Wall Duration
代表著這一塊區域的開始到結束的耗時,為204.877ms;CPU Duration
代表實際CPU在處理這一塊區域的耗時,即分配CPU的時長0.899ms。很顯然,這兩個時間差距非常大,CPU只消耗了不到1ms的時間來運算這塊區域。這就意味著可能其他執行緒/程式長期佔用CPU,導致RenderThread無法進行正常運算出現渲染異常。接下來,我們就通過分析Kernel CPU部分進一步確定是哪個執行緒/程式長期佔用CPU。
- Kernel CPU部分
在Kernel CPU區域,每一行代表一個CPU核心和它執行任務的時間片,放大後會看到每個色塊代表一個執行的程式,色塊的長度代表其執行時間。如下圖所示:
在之前選中的幀區域,我們很容易看到一個很長的綠色塊,位於CPU2上,這個綠色塊CPU執行的程式為HeapTaskDaemon,從程式名來看很容易猜出這個程式就是我們的GC守護程式。這就意味著,在這一幀內執行了長時間的垃圾回收操作,由於系統執行GC操作時會將正在執行的其他進行掛起,GC程式會獨佔CPU,長時間的GC操作或頻繁GC就會導致其他程式長時間分配不到CPU時間片,這就是導致渲染變慢的根本原因。我們點選HeapTaskDaemon顏色塊,可以看到具體的GC時間,如下圖所示:
操作快捷鍵
- W、S:放大、縮小
- A、D:向左、向右移動
需要注意的是,由於Systrace是以系統的角度返回一些資訊,只能提供一個大概且深度有限,我們可以用它來進行粗略的檢查,以便獲得具體分析的方向。如果需要進一步得到是哪塊程式碼引起的CPU繁忙、某些方法的呼叫次數等,就需要藉助TraceView這個工具進行。
2.2.2 TraceView
TraceView
是Android SDK中自帶的資料採集和分析工具,與Systrace
不同的是,它是從程式碼層面來分析效能問題,且針對的是每個方法來分析,比如當我們發現應用出現卡頓的時候,就可以通過TraceVIew
來分析出現卡頓時在方法的呼叫上有沒有很耗時的操作。開啟TraceView
方法與Systrace
一樣,都是在DDMS
中啟動。在使用TraceView
時,我們需要著重關注以下兩個方面:
- 呼叫次數不多,但是每一個執行都很耗時;
- 方法耗時不大,但是呼叫次數太多;
TraceView使用方法:
- 雙擊
sdk目錄/tools/monitor.bat
開啟DDMS,單擊DDMS皮膚上左上角帶小紅點按鈕,文字提示為start Method Profiling
,然後按鈕左上方會出現一個灰色的正方形,文字提示為stop Method Profiling
,此時按鈕變為停止採集功能; - 進入
Profiling Options
配置取樣頻率,預設為1000微秒; - 操作APP我們懷疑卡頓的地方,對該過程進行跟蹤;
- 操作結束後再次點選之前的按鈕(文字提示
stop Method Profiling
)結束採集。
從上圖可以看出,TraceView
的皮膚分上下兩個部分:
時間線皮膚
以每個執行緒為一行,右邊是該執行緒在整個過程中方法執行的情況;資料分析皮膚
是以表格的形式展示所有執行緒的方法的各項資料指標;
時間線皮膚:
時間線皮膚以每個執行緒為一行,右邊是該執行緒在整個過程中方法執行的情況,比如上圖中顯示的main執行緒就是Android應用的主執行緒,當然也會存在其他執行緒,可能會因操作不同而發生改變。每個執行緒的右邊對應的是該執行緒中每個方法的執行資訊,左邊為第一個方法執行開始,最右邊為最後一個方法執行結束,其中的每一個小立柱就代表一次方法的呼叫,你可以把滑鼠放到立柱上,就會顯示該方法呼叫的詳細資訊。
如上圖所示,墨綠色的立柱表示FibonacciActivity.computeFubonacci()
方法的執行情況,可以看出這個方法執行的時間很長,尤其是對於處於主執行緒中,這是非常不正常的現象。如果你想在分析皮膚中詳細檢視該方法,可以雙擊該立柱,資料分析皮膚自動跳轉到該方法。
資料分析皮膚:
資料分析皮膚右側為時間線皮膚中每個立柱表示的方法,當我點選墨綠色立柱後,FibonacciActivity.computeFubonacci()
方法被高亮,展開該方法我們可以看到Parents
和Children
,其中,Parents
表示誰呼叫了computeFubonacci()方法,Children
表示computeFubonacci()方法呼叫了哪些方法。資料分析皮膚的左側展示的是每個方法(一行)執行的耗時,我們著重看下computeFubonacci()方法Incl Real Time
值為1595.360ms,這顯然是不正常的。另外,再看下Calls+Recur Calls/Total
的值顯示computeFubonacci()方法數為1,但是被遞迴呼叫了1491次。因此,我們就可以得出之前的APP操作之所以會出現卡頓,是因為在主執行緒的FibonacciActivity中遞迴呼叫了computeFubonacci()方法,導致CPU被長期佔用,從而導致渲染執行緒無法獲得CPU資源出現無法正常渲染的效能問題。
每一列資料代表的含義如下表所示:
名稱 | 意義 |
---|---|
Name | 方法的詳細資訊,包括包名和引數資訊 |
Incl Cpu Time | Cpu執行該方法該方法及其子方法所花費的時間 |
Incl Cpu Time % | Cpu執行該方法該方法及其子方法所花費佔Cpu總執行時間的百分比 |
Excl Cpu Time | Cpu執行該方法所話費的時間 |
Excl Cpu Time % | Cpu執行該方法所話費的時間佔Cpu總時間的百分比 |
Incl Real Time | 該方法及其子方法執行所話費的實際時間 |
Incl Real Time % | 上述時間佔總的執行時間的百分比 |
Excl Real Time % | 該方法自身的實際允許時間 |
Excl Real Time | 上述時間佔總的允許時間的百分比 |
Calls+Recur Calls/Total | 呼叫次數+遞迴次數 |
Calls/Total | 呼叫次數和總次數的佔比 |
Cpu Time/Call | Cpu執行時間和呼叫次數的百分比,代表該函式消耗cpu的平均時間 |
Real Time/Call | 實際時間於呼叫次數的百分比,該表該函式平均執行時間 |
- FibonacciActivity原始碼如下:
/** UI卡頓現象
* @Auther: Jiangdg
* @Date: 2019/11/18 15:06
* @Description: 使用斐波那契數列人為製造卡頓現象
*/
public class FibonacciActivity extends AppCompatActivity {
private static final String LOG_TAG = "FibonacciActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fibonacci);
Button mbtn = (Button) findViewById(R.id.caching_do_fib_stuff);
mbtn.setText("計算斐波那契數列");
mbtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.i(LOG_TAG, String.valueOf(computeFibonacci(40)));
}
});
WebView webView = (WebView) findViewById(R.id.webview);
webView.getSettings().setUseWideViewPort(true);
webView.getSettings().setLoadWithOverviewMode(true);
webView.loadUrl("file:///android_asset/shiver_me_timbers.gif");
}
public int computeFibonacci(int positionInFibSequence) {
//0 1 1 2 3 5 8
if (positionInFibSequence <= 2) {
return 1;
} else {
return computeFibonacci(positionInFibSequence - 1)
+ computeFibonacci(positionInFibSequence - 2);
}
}
}
相關文章
- 六、Android效能優化之UI卡頓分析之渲染效能優化Android優化UI
- 前端不止:Web效能優化–關鍵渲染路徑以及優化策略前端Web優化
- UI效能優化UI優化
- React渲染效能優化React優化
- VUE 渲染效能優化Vue優化
- 效能優化(二) UI 繪製優化優化UI
- Android 效能優化 ---- 啟動優化Android優化
- Android效能優化----卡頓優化Android優化
- Android效能優化Android優化
- Android效能優化——圖片優化(二)Android優化
- Android效能優化之佈局優化Android優化
- Android效能優化(1)—webview優化篇Android優化WebView
- Android效能優——佈局優化Android優化
- Android效能優化——效能優化的難題總結Android優化
- Android效能優化(Memory)Android優化
- Android 效能優化之記憶體優化Android優化記憶體
- Android效能優化篇之服務優化Android優化
- Java gc(垃圾回收機制)小結,以及Android優化建議JavaGCAndroid優化
- Android效能優化筆記(一)——啟動優化Android優化筆記
- Android效能優化 筆記Android優化筆記
- Android 效能優化(十二)之我為什麼寫效能優化Android優化
- React 效能優化 - 避免重複渲染React優化
- 使用 content-visibility 優化渲染效能優化
- MySQL效能優化(九)-- 鎖機制之行鎖MySql優化
- android記憶體管理機制與優化Android記憶體優化
- 網站效能優化實戰(二)——深入淺出瀏覽器渲染機制網站優化瀏覽器
- mysql鎖機制總結,以及優化建議MySql優化
- 機房合作UI優化UI優化
- 【前端效能優化】vue效能優化前端優化Vue
- UI技術總結--效能優化UI優化
- 關於UI事件傳遞,影像顯示,效能優化,離屏渲染UI事件優化
- Android效能優化——列表類控制元件卡頓優化Android優化控制元件
- Android效能優化全方面解析Android優化
- 使用React中後臺效能優化以及移動端優化React優化
- 使用vue中後臺效能優化以及移動端優化Vue優化
- css 渲染優化CSS優化
- webpack4.x 效能優化Web優化
- 4、React元件之效能優化React元件優化