新聞中心
Android流暢度評估及卡頓優(yōu)化
Google定義:界面呈現(xiàn)是指從應用生成幀并將其顯示在屏幕上的動作。要確保用戶能夠流暢地與應用互動,應用呈現(xiàn)每幀的時間不應超過16ms,以達到每秒60幀的呈現(xiàn)速度(為什么是60fps?)。
成都創(chuàng)新互聯(lián)長期為上1000+客戶提供的網(wǎng)站建設服務,團隊從業(yè)經(jīng)驗10年,關(guān)注不同地域、不同群體,并針對不同對象提供差異化的產(chǎn)品和服務;打造開放共贏平臺,與合作伙伴共同營造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為新源企業(yè)提供專業(yè)的成都網(wǎng)站建設、網(wǎng)站建設,新源網(wǎng)站改版等技術(shù)服務。擁有十余年豐富建站經(jīng)驗和眾多成功案例,為您定制開發(fā)。
如果應用存在界面呈現(xiàn)緩慢的問題,系統(tǒng)會不得不跳過一些幀,這會導致用戶感覺應用不流暢,我們將這種情況稱為卡頓。
來源于: Google Android的為什么是60fps?
16ms意味著1000/60hz,相當于60fps。這是因為人眼與大腦之間的協(xié)作無法感知超過60fps的畫面更新。12fps大概類似手動快速翻動書籍的幀率, 這明顯是可以感知到不夠順滑的。24fps使得人眼感知的是連續(xù)線性的運動,這其實是歸功于運動模糊的效果。 24fps是電影膠圈通常使用的幀率,因為這個幀率已經(jīng)足夠支撐大部分電影畫面需要表達的內(nèi)容,同時能夠最大的減少費用支出。 但是低于30fps是 無法順暢表現(xiàn)絢麗的畫面內(nèi)容的,此時就需要用到60fps來達到想要的效果,超過60fps就沒有必要了。如果我們的應用沒有在16ms內(nèi)完成屏幕刷新的全部邏輯操作,就會發(fā)生卡頓。
首先要了解Android顯示1幀圖像,所經(jīng)歷的完整過程。
如圖所示,屏幕顯示1幀圖像需要經(jīng)歷5個步驟:
常見的丟幀情況: 渲染期間可能出現(xiàn)的情況,渲染大于16ms和小于16ms的情況:
上圖中應該繪制 4 幀數(shù)據(jù) , 但是實際上只繪制了 3 幀 , 實際幀率少了一幀
判斷APP是否出現(xiàn)卡頓,我們從通用應用和游戲兩個緯度的代表公司標準來看,即Google的Android vitals性能指標和地球第一游戲大廠騰訊的PrefDog性能指標。
以Google Vitals的卡頓描述為準,即呈現(xiàn)速度緩慢和幀凍結(jié)兩個維度判斷:
PerfDog Jank計算方法:
幀率FPS高并不能反映流暢或不卡頓。比如:FPS為50幀,前200ms渲染一幀,后800ms渲染49幀,雖然幀率50,但依然覺得非常卡頓。同時幀率FPS低,并不代表卡頓,比如無卡頓時均勻FPS為15幀。所以平均幀率FPS與卡頓無任何直接關(guān)系)
當了解卡頓的標準以及渲染原理之后,可以得出結(jié)論,只有丟幀情況才能準確判斷是否卡頓。
dumpsys 是一種在設備上運行并轉(zhuǎn)儲需要關(guān)注的系統(tǒng)服務狀態(tài)信息的 Android 工具。通過向 dumpsys 傳遞 gfxinfo 命令,可以提供 logcat 格式的輸出,其中包含與錄制階段發(fā)生的動畫幀相關(guān)的性能信息。
借助 Android 6.0(API 級別 23),該命令可將在整個進程生命周期中收集的幀數(shù)據(jù)的聚合分析輸出到 logcat。例如:
這些總體統(tǒng)計信息可以得到期間的FPS、Jank比例、各類渲染異常數(shù)量統(tǒng)計。
命令 adb shell dumpsys gfxinfo PACKAGE_NAME framestats 可提供最近120個幀中,渲染各階段帶有納秒時間戳的幀時間信息。
關(guān)鍵參數(shù)說明:
通過gfxinfo輸出的幀信息,通過定時reset和打印幀信息,可以得到FPS(幀數(shù)/打印間隔時間)、丟幀比例((janky_frames / total_frames_rendered)*100 %)、是否有幀凍結(jié)(幀耗時700ms)。
根據(jù)第2部分的通用應用卡頓標準,可以通過丟幀比例和幀凍結(jié)數(shù)量,準確判斷當前場景是否卡頓。并且通過定時截圖,還可以根據(jù)截圖定位卡頓的具體場景。
如上圖所示,利用gfxinfo開發(fā)的檢查卡頓的小工具,圖中參數(shù)和卡頓說明如下:
根據(jù)上面對gfxinfo的幀信息解析,可以準確計算出每一幀的耗時。從而可以開發(fā)出滿足騰訊PerfDog中關(guān)于普通卡頓和嚴重卡頓的判斷。
依賴定時截圖,即可準確定位卡頓場景。如下圖所示(此處以PerfDog截圖示例):
通過第3部分的卡頓評估方法,我們可以定位到卡頓場景,但是如何定位到具體卡頓原因呢。
首先了解卡頓問題定位工具,然后再了解常見的卡頓原因,即可通過復現(xiàn)卡頓場景的同時,用工具去定位具體卡頓問題。
重點就是,充分利用gfxinfo輸出的幀信息,對卡頓問題進行分類。
了解了高效定位卡頓的方法和卡頓問題定位工具,再熟悉一下常見的卡頓原因,可以更熟練的定位和優(yōu)化卡頓。
SurfaceFlinger 負責 Surface 的合成,一旦 SurfaceFlinger 主線程調(diào)用超時,就會產(chǎn)生掉幀。
SurfaceFlinger 主線程耗時會也會導致 hwc service 和 crtc 不能及時完成,也會阻塞應用的 binder 調(diào)用,如 dequeueBuffer、queueBuffer 等。
后臺進程活動太多,會導致系統(tǒng)非常繁忙,cpu \ io \ memory 等資源都會被占用,這時候很容易出現(xiàn)卡頓問題,這也是系統(tǒng)這邊經(jīng)常會碰到的問題。
dumpsys cpuinfo 可以查看一段時間內(nèi) cpu 的使用情況:
當線程為 Runnable 狀態(tài)的時候,調(diào)度器如果遲遲不能對齊進行調(diào)度,那么就會產(chǎn)生長時間的 Runnable 線程狀態(tài),導致錯過 Vsync 而產(chǎn)生流暢性問題。
system_server 的 AMS 鎖和 WMS 鎖 , 在系統(tǒng)異常的情況下 , 會變得非常嚴重 , 如下圖所示 , 許多系統(tǒng)的關(guān)鍵任務都被阻塞 , 等待鎖的釋放 , 這時候如果有 App 發(fā)來的 Binder 請求帶鎖 , 那么也會進入等待狀態(tài) , 這時候 App 就會產(chǎn)生性能問題 ; 如果此時做 Window 動畫 , 那么 system_server 的這些鎖也會導致窗口動畫卡頓。
Android P 修改了 Layer 的計算方法 , 把這部分放到了 SurfaceFlinger 主線程去執(zhí)行, 如果后臺 Layer 過多,就會導致 SurfaceFlinger 在執(zhí)行 rebuildLayerStacks 的時候耗時 , 導致 SurfaceFlinger 主線程執(zhí)行時間過長。
主線程執(zhí)行 Input \ Animation \ Measure \ Layout \ Draw \ decodeBitmap 等操作超時都會導致卡頓 。
Activity resume 的時候, 與 AMS 通信要持有 AMS 鎖, 這時候如果碰到后臺比較繁忙的時候, 等鎖操作就會比較耗時, 導致部分場景因為這個卡頓, 比如多任務手勢操作。
應用里面涉及到 WebView 的時候, 如果頁面比較復雜, WebView 的性能就會比較差, 從而造成卡頓。
如果屏幕幀率和系統(tǒng)的 fps 不相符 , 那么有可能會導致畫面不是那么順暢. 比如使用 90 Hz 的屏幕搭配 60 fps 的動畫。
由上面的分析可知對象分配、垃圾回收(GC)、線程調(diào)度以及Binder調(diào)用 是Android系統(tǒng)中常見的卡頓原因,因此卡頓優(yōu)化主要以下幾種方法,更多的要結(jié)合具體的應用來進行:
在計算機和通信領(lǐng)域,幀是一個包括“幀同步串行”的數(shù)字數(shù)據(jù)傳輸單元或數(shù)字數(shù)據(jù)包。
在視頻領(lǐng)域,電影、電視、數(shù)字視頻等可視為隨時間連續(xù)變換的許多張畫面,其中幀是指每一張畫面。
Android App內(nèi)存優(yōu)化
內(nèi)存優(yōu)化就是對內(nèi)存問題的一個預防和解決,做內(nèi)存優(yōu)化能讓應用掛得少、活得好和活得久。
掛的少:
“掛”指的是 Crash,內(nèi)存問題導致 Crash 的具體表現(xiàn)就是內(nèi)存溢出異常 OOM。
活得好:
活得好指的是使用流暢,Android 中造成界面卡頓的原因有很多種,其中一種就是由內(nèi)存問題引起的。內(nèi)存問題之所以會影響到界面流暢度,是因為垃圾回收(GC,Garbage Collection),在 GC 時,所有線程都要停止,包括主線程,當 GC 和繪制界面的操作同時觸發(fā)時,繪制的執(zhí)行就會被擱置,導致掉幀,也就是界面卡頓。
活得久:
活得久指的是我們的應用在后臺運行時不會被干掉。Android 會按照特定的機制清理進程,清理進程時優(yōu)先會考慮清理后臺進程。清理進程的機制就是LowMemoryKiller。在 Android 中不同的進程有著不同的優(yōu)先級,當兩個進程的優(yōu)先級相同時,低殺會優(yōu)先考慮干掉消耗內(nèi)存更多的進程。也就是如果我們應用占用的內(nèi)存比其他應用少,并且處于后臺時,我們的應用能在后臺活下來,這也是內(nèi)存優(yōu)化為我們應用帶來競爭力的一個直接體現(xiàn)。
內(nèi)存占用是否越少越好?
當系統(tǒng) 內(nèi)存充足 的時候,我們可以多用 一些獲得更好的性能。當系統(tǒng) 內(nèi)存不足 的時候,我們希望可以做到 ”用時分配,及時釋放“。內(nèi)存優(yōu)化并不能一刀切。
我們都知道,應用程序的內(nèi)存分配和垃圾回收都是由Android虛擬機完成的,在Android 5.0以下,使用的是Dalvik虛擬機,5.0及以上,則使用的是ART虛擬機。
Android虛擬機Dalvik和ART
1、內(nèi)存區(qū)域劃分
詳細請看以下兩篇文章(建議全看):
java內(nèi)存四大區(qū)_JVM內(nèi)存區(qū)域劃分
Android 內(nèi)存機制
2、內(nèi)存回收
垃圾收集的標記算法(找到垃圾):
垃圾收集算法(回收垃圾):
引用類型:強引用、軟引用、弱引用、虛引用
對象的有效性=可達性+引用類型
JAVA垃圾回收機制-史上最容易理解看這一篇就夠了
Android:玩轉(zhuǎn)垃圾回收機制與分代回收策略
android中還存在低殺機制,這種情況屬于系統(tǒng)整機內(nèi)存不足,直接把應用進程殺掉的情況。
Android后臺殺死系列:LowMemoryKiller原理
1、內(nèi)存溢出
系統(tǒng)會給每個App分配內(nèi)存空間也就是heap size值,當app占用的內(nèi)存加上申請的內(nèi)存超過這個系統(tǒng)分配的內(nèi)存限額,最終導致OOM(OutOfMemory)使程序崩潰。
通過命令 getprop |grep dalvik.vm.heapsize 可以獲取系統(tǒng)允許的最大
注意:在設置了heapgrowthlimit的狀況下,單個進程可用最大內(nèi)存為heapgrowthlimit值。在android開發(fā)中,若是要使用大堆,須要在manifest中指定android:largeHeap為true,這樣dvm heap最大可達heapsize。
關(guān)于heapsize heapgrowthlimit
2、內(nèi)存泄漏
Android系統(tǒng)虛擬機的垃圾回收是通過虛擬機GC機制來實現(xiàn)的。GC會選擇一些還存活的對象作為內(nèi)存遍歷的根節(jié)點GC Roots,通過對GC Roots的可達性來判斷是否需要回收。內(nèi)存泄漏就是 在當前應用周期內(nèi)不再使用的對象被GC Roots引用,造成該對象無法被系統(tǒng)回收,以致該對象在堆中所占用的內(nèi)存單元無法被釋放而造成內(nèi)存空間浪費,使實際可使用內(nèi)存變小。簡言之,就是 對象被持有導致無法釋放或不能按照對象正常的生命周期進行釋放。
Android常見內(nèi)存泄漏匯總
3、內(nèi)存抖動
指的是在短時間內(nèi)大量的新對象被實例化,運行時可能無法承載這樣的內(nèi)存分配,在這種情況下就會導致垃圾回收事件被大量調(diào)用,影響到應用程序的UI和整體性能,最終可能導致卡頓和OOM。
常見情況:在一些被頻繁調(diào)用的方法內(nèi)不斷地創(chuàng)建對象。例如在View 的onDraw方法內(nèi)new 一些新的對象。
注意內(nèi)存抖動也會導致 OOM,主要原因有如下兩點:
1、Android Studio Profiler
作用
優(yōu)點
內(nèi)存抖動問題處理實戰(zhàn)
理解內(nèi)存抖動的概念的話,我們就能明白只要能找到抖動過程中所產(chǎn)生的對象及其調(diào)用棧,我們就能解決問題,剛好Android Studio 的Porfiler里面的Memory工具就能幫我們記錄下我們操作過程中或靜止界面所產(chǎn)生的新對象,并且能清晰看到這些對象的調(diào)用棧。
選擇Profile 中 的Memory ,選擇 Record Java/Kotlin allocations,再點擊Record開始記錄, Record Java/Kotlin allocations 選項會記錄下新增的對象。
操作完成之后,點擊如圖所示的紅腦按鈕,停止記錄。
停止記錄后,我們就可以排序(點擊 Allocations可以排序)看看哪些對象或基本類型在短時間被頻繁創(chuàng)建多個,點擊這些新增的對象就可以看到它的完成的調(diào)用鏈了,進而就找找到導致內(nèi)存抖動的地方在哪里了。
2、利用DDMS 和 MAT(Memory Analyzer tool)來分析內(nèi)存泄漏
我們利用工具進行內(nèi)存泄漏分析主要是用對比法:
a.先打開正常界面,不做任何操作,先抓取一開始的堆文件。
b.一頓胡亂操作,回到原來操作前的界面。主動觸發(fā)一兩次GC,過10秒再抓取第二次堆文件。
c.通過工具對比,獲取胡亂操作后新增的對象,然后分析這些新增的對象。
DDMS作用:抓取堆文件,主動觸發(fā)GC。(其實也是可以用Android Studio 的Profile里面的Memory工具來抓取堆文件的,但是我這邊在利用Profile 主動觸發(fā)gc 的時候會導致程序奔潰,也不知道是不是手機的問題,所以沒用Android Studio的Profiler)
MAT作用:對堆文件進行對比,找到多出的對象,找到對象的強引用調(diào)用鏈。
以下是詳細的過程:
步驟1.打開DDMS,選擇需要調(diào)試的應用,打開初始界面,點擊下圖的圖標(Dump Hprof File)先獲取一次堆文件。
步驟2.對應用隨便操作后,回到一開始的界面,先多觸發(fā)幾次GC ,點擊下圖的圖標(Cause Gc)來主動觸發(fā)GC,然后再次點擊 Dump Hprof File 圖標來獲取堆文件。
步驟3.通過Android Studio Profile 或者 DDMS dump 的堆文件無法在MAT 打開,需要借助android sdk包下的一個工具hprof-conv.exe來轉(zhuǎn)換。
格式為 hprof-conv 舊文件路徑名 要轉(zhuǎn)換的名稱;
例如:hprof-conv 2022-04-13_17-54-40_827.hprof change.hprof
步驟4.把兩份堆文件導入MAT,然后選擇其中第二次獲取的堆文件,點擊 如圖所示的 Histogram查看。
步驟5.點擊下圖圖標,Compare To Another Heap Dump ,選擇另一份堆文件。
6.會得出下圖所示的 Hitogram 展示,我們主要看Objects 這一列。 如下圖所示 “+ 2” 則代表前面兩份堆文件對比,這個對象多了兩個,我們主要就是要分析這些多了出來,沒有被回收的對象。
7.加入我們從增加的對象中,看到了MainActivity ,則需要從一開始打開的Hitogram 展示里面找到這個對象的調(diào)用棧。如下圖所示,搜索MainActivity
8.看到下圖所示解雇,然后鼠標右鍵點擊下圖紅色圈圈著的MainActivity ,選擇 Merger Shortest Paths to Gc Roots ,再選擇 exclude all phantom/weak/soft etc.references ,就可以看到這個MainActivity 對象的強引用鏈,至此我們就可以找到MainActivity對象是被什么引用導致無法回收了。
3、內(nèi)存泄露檢測神器之LeakCanary(線下集成)
自行學習了解,接入簡單,使用簡單,基本可以解決大部分內(nèi)存泄漏問題。
github地址 :
學習地址 :
針對內(nèi)存抖動的建議:
針對內(nèi)存泄漏問題的建議:
針對內(nèi)存溢出問題的建議(主要就是要減少內(nèi)存占用):
建議參考:
深入探索 Android 內(nèi)存優(yōu)化(煉獄級別)
對于 優(yōu)化的大方向,我們應該優(yōu)先去做見效快的地方,主要有以下三部分:內(nèi)存泄漏、內(nèi)存抖動、Bitmap。完善監(jiān)控機制也是我們的重點,能幫助我們對內(nèi)存問題快速分析和處理。
參考:
深入探索 Android 內(nèi)存優(yōu)化(煉獄級別)
Android性能優(yōu)化之耗電優(yōu)化
通過上圖先把用戶-電量這一流程抽象出來,設備的耗電根本原因在于對硬件的使用,耗電越嚴重說明對硬件使用的越頻繁。用戶對app頻繁使用說明了你用戶黏性做的好,我們不能左右,所以我們要在app對硬件調(diào)用上做優(yōu)化來達到節(jié)省電量的目的。
先看下移動設備元件耗電大戶有哪些:
屏幕是耗電最大元件之一,但是用戶要和app交互就要點亮屏幕,有人可能會覺得屏幕的明暗是用戶自己根據(jù)喜好設定的,我們無可奈何。其實不然,在有些時候是可以通過UI的設計來減少屏幕電能消耗的。
在這之前我們先來看下目前常用手機屏幕材質(zhì):LCD和LED(OLED)。
無線網(wǎng)絡主要是WIFI和移動運營商網(wǎng)絡,通常情況下使用移動網(wǎng)絡要比WIFI耗電要多一些。
這三種狀態(tài)有一個轉(zhuǎn)換流程:
通過上面了解網(wǎng)絡連接過程,應該心里有了大概的優(yōu)化建議。
精簡后
①請求一個圖片時,客戶端提供一個分辨率大小,服務器根據(jù)分辨率把裁剪縮放后的圖片給客戶端返回。也可以使用Android端使用Bitmap.Option自行獲取縮放的圖片
②使用webp圖片。
后面的章節(jié)會寫一些關(guān)于電量檢測分析工具的使用。
為了耗電優(yōu)化干的這些活用戶感知不到,但是如果不去優(yōu)化,肆意使用,那用戶就很容易感知到了。
Android性能優(yōu)化總結(jié)
常用的Android性能優(yōu)化方法:
一、布局優(yōu)化:
1)盡量減少布局文件的層級。
層級少了,繪制的工作量也就少了,性能自然提高。
2)布局重用 include標簽
3)按需加載:使用ViewStub,它繼承自View,一種輕量級控件,本身不參與任何的布局和繪制過程。他的layout參數(shù)里添加一個替換的布局文件,當它通過setVisibility或者inflate方法加載后,它就會被內(nèi)部布局替換掉。
二、繪制優(yōu)化:
基于onDraw會被調(diào)用多次,該方法內(nèi)要避免兩類操作:
1)創(chuàng)建新的局部對象,導致大量垃圾對象的產(chǎn)生,從而導致頻繁的gc,降低程序的執(zhí)行效率。
2)不要做耗時操作,搶CPU時間片,造成繪制很卡不流暢。
三、內(nèi)存泄漏優(yōu)化:
1)靜態(tài)變量導致內(nèi)存泄漏 ? 比較明顯
2)單例模式導致的內(nèi)存泄漏?單例無法被垃圾回收,它持有的任何對象的引用都會導致該對象不會被gc。
3)屬性動畫導致內(nèi)存泄漏 ?無限循環(huán)動畫,在activity中播放,但是onDestroy時沒有停止的話,動畫會一直播放下去,view被動畫持有,activity又被view持有,導致activity無法被回收。
四、響應速度優(yōu)化:
1)避免在主線程做耗時操作 包括四大組件,因為四大組件都是運行在主線程的。
2)把一些創(chuàng)建大量對象等的初始化工作放在頁面回到前臺之后,而不應該放到創(chuàng)建的時候。
五、ListView的優(yōu)化:
1)使用convertView,走listView子View回收的一套:RecycleBin 機制
主要是維護了兩個數(shù)組,一個是mActiveViews,當前可見的view,一個是mScrapViews,當前不可見的view。當觸摸ListView并向上滑動時,ListView上部的一些OnScreen的View位置上移,并移除了ListView的屏幕范圍,此時這些OnScreen的View就變得不可見了,不可見的View叫做OffScreen的View,即這些View已經(jīng)不在屏幕可見范圍內(nèi)了,也可以叫做ScrapView,Scrap表示廢棄的意思,ScrapView的意思是這些OffScreen的View不再處于可以交互的Active狀態(tài)了。ListView會把那些ScrapView(即OffScreen的View)刪除,這樣就不用繪制這些本來就不可見的View了,同時,ListView會把這些刪除的ScrapView放入到RecycleBin中存起來,就像把暫時無用的資源放到回收站一樣。
當ListView的底部需要顯示新的View的時候,會從RecycleBin中取出一個ScrapView,將其作為convertView參數(shù)傳遞給Adapter的getView方法,從而達到View復用的目的,這樣就不必在Adapter的getView方法中執(zhí)行LayoutInflater.inflate()方法了。
RecycleBin中有兩個重要的View數(shù)組,分別是mActiveViews和mScrapViews。這兩個數(shù)組中所存儲的View都是用來復用的,只不過mActiveViews中存儲的是OnScreen的View,這些View很有可能被直接復用;而mScrapViews中存儲的是OffScreen的View,這些View主要是用來間接復用的。
2)使用ViewHolder避免重復地findViewById
3)快速滑動不適合做大量異步任務,結(jié)合滑動監(jiān)聽,等滑動結(jié)束之后加載當前顯示在屏幕范圍的內(nèi)容。
4)getView中避免做耗時操作,主要針對圖片:ImageLoader來處理(原理:三級緩存)
5)對于一個列表,如果刷新數(shù)據(jù)只是某一個item的數(shù)據(jù),可以使用局部刷新,在列表數(shù)據(jù)量比較大的情況下,節(jié)省不少性能開銷。
六、Bitmap優(yōu)化:
1)減少內(nèi)存開支:圖片過大,超過控件需要的大小的情況下,不要直接加載原圖,而是對圖片進行尺寸壓縮,方式是BitmapFactroy.Options 采樣,inSampleSize 轉(zhuǎn)成需要的尺寸的圖片。
2)減少流量開銷:對圖片進行質(zhì)量壓縮,再上傳服務器。圖片有三種存在形式:硬盤上時是file,網(wǎng)絡傳輸時是stream,內(nèi)存中是stream或bitmap,所謂的質(zhì)量壓縮,它其實只能實現(xiàn)對file的影響,你可以把一個file轉(zhuǎn)成bitmap再轉(zhuǎn)成file,或者直接將一個bitmap轉(zhuǎn)成file時,這個最終的file是被壓縮過的,但是中間的bitmap并沒有被壓縮。bitmap.compress(Bitmap.CompressFormat.PNG,100,bos);
七、線程優(yōu)化:
使用線程池。為什么要用線程池?
1、從“為每個任務分配一個線程”轉(zhuǎn)換到“在線程池中執(zhí)行任務”
2、通過重用現(xiàn)有的線程而不是創(chuàng)建新線程,可以處理多個請求在創(chuàng)建銷毀過程中產(chǎn)生的巨大開銷
3、當使用線程池時,在請求到來時間 ,不用等待系統(tǒng)重新創(chuàng)建新的線程,而是直接復用線程池中的線程,這樣可以提高響應性。
4、通過和適當調(diào)整線程池的大小 ,可以創(chuàng)建足夠多的線程以使處理器能夠保持忙碌狀態(tài),同時還可以防止過多線程相互競爭資源而使應用程序耗盡內(nèi)存或者失敗。
5、一個App里面所有的任務都放在線程池中執(zhí)行后,可以統(tǒng)一管理 ,當應用退出時,可以把程序中所有的線程統(tǒng)一關(guān)閉,避免了內(nèi)存和CPU的消耗。
6、如果這個任務是一個循環(huán)調(diào)度任務,你則必須在這個界面onDetach方法把這個任務給cancel掉,如果是一個普通任務則可cancel,可不cancel,但是最好cancel
7、整個APP的總開關(guān)會在應用退出的時間把整個線程池全部關(guān)閉。
八、一些性能優(yōu)化建議:
1)避免創(chuàng)建過多對象,造成頻繁的gc
2)不要過多使用枚舉,枚舉占用的空間比整型大很多
3)字符串的拼接使用StringBuffer、StringBuilder來替代直接使用String,因為使用String會創(chuàng)建多個String對象,參考第一條。
4)適當使用軟引用,(弱引用就不太推薦了)
5)使用內(nèi)存緩存和磁盤緩存。
Android啟動優(yōu)化概述
Android啟動應用, 按 官方說法 分為冷啟動, 溫啟動和熱啟動.
具體的定義可以看官方文檔, 簡單地說
一般我們只需要關(guān)注冷啟動即可.
要想啟動快, 硬件性能必然有影響, 在硬件一定的前提下, 我們要盡量 降低啟動應用時CPU的負載 , 讓CPU有更多的算力投入到啟動流程中:
在做好一些基本原則后, 接著看具體的流程優(yōu)化點
在應用進程創(chuàng)建后, 首先必然是加載類, 此時一些靜態(tài)變量就會初始化了, 因此我們應該
類加載完畢后就是創(chuàng)建 Application 實例了, 因此我們應該
之后會先創(chuàng)建 ContentProvider 和執(zhí)行 ContentProvider.onCreate() , 因此我們應該
跟接著就會執(zhí)行 Application.onCreate() 等方法, 因此我們應該
接著就進入 Activity 環(huán)節(jié).
同樣第一步會是創(chuàng)建實例, 因此我們應該
在 Activity 進程生命周期后, 第一步就是渲染(inflate)布局, 我們應該
在應用啟動的瞬間, 系統(tǒng)服務會先展示一個空白窗口, 等待應用第一幀繪制完畢后, 再從該窗口切換到應用, 如果啟動耗時較長, 就會明顯看到白屏, 對于這一點, 常見的操作有
可以使用IdleHandler, 在主線程空閑時再執(zhí)行某些不重要的操作
實際上異步初始化只是不阻塞主線程, 但是子線程一樣會占用CPU資源, 讓主線程的執(zhí)行時間變少, 所以不應該盲目地將所有工作放到子線程.
優(yōu)化做到最后, 就是在系統(tǒng)流程上做文章了
原理是將啟動時加載的類放到主dex,提升了這些類的內(nèi)聚,讓更多的類滿足pre-verify的條件,在安裝時就做了校驗和優(yōu)化,以減少首次加載的耗時,從而優(yōu)化冷啟動耗時。
Redex 初探與 Interdex:Andorid 冷啟動優(yōu)化
應用啟動過程中會從apk壓縮包中讀取文件, 該優(yōu)化的原理是利用Linux中的Pagecache機制, 讓啟動過程會用到的文件盡可能進入緩存中, 減少磁盤IO次數(shù)
支付寶 App 構(gòu)建優(yōu)化解析:通過安裝包重排布優(yōu)化 Android 端啟動性能
在Dalvik VM(Android5.0以前)加載類的時候會有一個類校驗過程, 它需要校驗方法的每一個指令, 是一個比較耗時的過程, 可以通過Hook去掉類加載過程中的類驗證過程. 不過對于ART(Android5.0之后)來說, 這個過程在安裝時已經(jīng)做了, 所以用處不大.
不進入冷啟動, 就不用優(yōu)化了~
這個Android Studio自帶的工具, 可以看到啟動過程中詳細的方法執(zhí)行流程, 但是采集數(shù)據(jù)本身會影響方法執(zhí)行, 所以不能準確判斷每個方法的耗時, 但是仍可以判斷哪個方法相對來說耗時.
這個工具的好處是可以自定義事件, 可以指定需要采集的數(shù)據(jù)集, 可以看到線程間的狀態(tài)等.
啟動優(yōu)化的一個關(guān)鍵點在于定義啟動結(jié)束的點, 以及如何測量啟動時間.
在Android4.4以上, 系統(tǒng)進程會提供一個類似 ActivityManager: Displayed ***: +3s534ms 的日志, 表示從啟動進程到首次繪制完畢所用的時間.
應用可以在任何時候調(diào)用該方法, 觸發(fā)系統(tǒng)打印類似 system_process I/ActivityManager: Fully drawn {package}/.MainActivity: +1s54ms 的日志
應用可以通過 ViewTreeObserver 來監(jiān)聽繪制前回調(diào)來判斷第一幀的繪制時機, 或者直接在控件樹的末尾加一個簡單的View, 它 onDraw 調(diào)用時即表示頁面(差不多)繪制完畢.
應用啟動過程可以參考 Android Vitals Series' Articles 系列文章
Android手機系統(tǒng)優(yōu)化方法
1. 手機一鍵優(yōu)化 :包含內(nèi)存占用、手機存儲、系統(tǒng)內(nèi)存優(yōu)化、垃圾文件清理四個選擇,點擊“一鍵優(yōu)化”即可。不僅可以顯著的提高手機運行速度,還可以節(jié)省存儲卡空間、降低手機CPU使用率,不再糾結(jié)于智能手機的卡吧-死機- -!
使用竅門:手機開機一段時間后或者玩大型游戲前點一下,最簡單最快速提升系統(tǒng)性能和速度。
2. 清理網(wǎng)絡緩存 :網(wǎng)絡程序占用的緩存管理,可以節(jié)省手機內(nèi)存空間和提高上網(wǎng)速度。很常遇到的'一個現(xiàn)象,APK安裝包體積很少,但運行一段時間后缺累積了上M的緩存,導致整體在手機內(nèi)存空間占用率高,內(nèi)存空間越少,系統(tǒng)所能裝的軟件就會越少了,經(jīng)常性的清理網(wǎng)絡緩存能使您的手機能裝更多的軟件。
單個操作:點擊程序圖標進入,點擊“清除緩存”即可清理該程序緩存,點擊手機“返回”按鍵,即可返回系統(tǒng)優(yōu)化界面。
批量操作:點擊“清理網(wǎng)絡緩存”按鈕進入,點擊“清除緩存”即可清理當前程序緩存,點擊手機“返回”按鍵,即可進入下一個程序操作界面,所有程序清理完成后,點擊手機“返回”按鍵,返回系統(tǒng)優(yōu)化界面。
3. 默認程序管理 :管理手機系統(tǒng)默認的執(zhí)行程序,比如上網(wǎng)默認打開的瀏覽器(ucweb,QQ瀏覽器等)、音樂默認播放程序(酷狗,天天動聽)等。目前暫時只支持單個設置。
單個操作:點擊程序圖標進入,點擊“清除默認設置”即可,點擊手機“返回”按鍵,即可返回系統(tǒng)優(yōu)化界面。
批量操作:點擊“重置以上默認打開程序”進入,點擊“清除默認設置”即可清除當前程序設置,點擊手機“返回”按鍵,即可進入下一個程序操作界面,所有程序清理完成后,點擊手機“返回”按鍵,返回系統(tǒng)優(yōu)化界面。
4. 手機節(jié)電優(yōu)化 :可以進行節(jié)電優(yōu)化和查看電視狀態(tài)、使用詳情。
點擊“節(jié)點優(yōu)化(21項)”進入,可以看到21條android手機節(jié)點秘籍,根據(jù)文字操作即可,讓你的手機擁有超長的待機時間。
分享題目:android優(yōu)化,Android優(yōu)化大師源碼
本文鏈接:http://www.ef60e0e.cn/article/phcsdd.html