- 做開發除了實現功能,還要注重優化,性能優化包括的東西還是非常多的,包體大小、啟動速度、內存、數據結構、ANR、卡頓等等。
- 用戶都希望APP按下,就能馬上進入首頁使用,手機性能很重要,但不能要求用戶換手機,于是我們就需要APP想辦法優化啟動的速度,不然這APP可能會被刪掉。
- Android性能優化 - 卡頓和布局優化 可以一起學習。
1.啟動的狀態
- 我們APP不是微信那種體量,所以幾乎不可能有廠商給我們搞特殊,一直掛在那,大多數情況下都是冷啟動,優化也是主要優化冷啟動。
-
冷啟動
冷啟動是指應用從頭開始啟動:系統進程在冷啟動后才創建應用進程。發生冷啟動的情況包括應用自設備啟動后或系統終止應用后首次啟動。 -
熱啟動
在熱啟動中,系統的所有工作就是將 Activity 帶到前臺。只要應用的所有 Activity 仍駐留在內存中,應用就不必重復執行對象初始化、布局加載和繪制。比如回到桌面,不殺掉APP的時間內又回來。 -
溫啟動
溫啟動包含了在冷啟動期間發生的部分操作;同時,它的開銷要比熱啟動高。有許多潛在狀態可視
為溫啟動。例如:
1.用戶在退出應用后又重新啟動應用。進程可能未被銷毀,繼續運行,但應用需要執行
onCreate() 從頭開始重新創建 Activity。
2.系統將應用從內存中釋放,然后用戶又重新啟動它。進程和 Activity 需要重啟,但傳遞到
onCreate() 的已保存的實例 state bundle 對于完成此任務有一定助益。
2.冷啟動耗時
- 2-5-8原則:
- 當用戶能夠在2秒以內得到響應時,會感覺系統的響應很快;
- 當用戶在2-5秒之間得到響應時,會感覺系統的響應速度還可以;
- 當用戶在5-8秒以內得到響應時,會感覺系統的響應速度很慢,但是還可以接受;
- 而當用戶在超過8秒后仍然無法得到響應時,會感覺系統糟透了,或者認為系統已經失去響應。
2.1 系統日志統計
- 在Logcat,篩選 Displayed,就能看到啟動時長。
-
這個時長就是應用啟動到顯示對應的Activity繪制完成的時長。(下圖就是啟動到MainActivity)
日志查看啟動時長
2.2 adb命令統計
-
adb需要配置環境變量,只需要把 sdk 目錄下的 platform-tools 路徑添加到 環境變量path 里面就行。
配置adb環境變量 adb shell
am shart -S -W com.bao.myapplication/.MainActivity
根據自己的包名和要啟動的Activity輸入這兩行命令就可以看到啟動時間。
-
TotalTime就是啟動時長啦。
adb查看啟動時長
3.啟動分析
- 工具詳情可以查看官方文檔:使用 CPU 性能剖析器檢查 CPU 活動。
在這里插入圖片描述
3.1 CPU Profile工具簡單教程
Android Studio 功能越來越完善,我們可以利用 CPU Profile 來查看分析啟動時做了什么事情。
-
點擊 app -> Edit Configurations。
cpu profile Profilling -> Start recording CPU activity on startup。
-
選擇CPU記錄配置 Trace Java Methods。
選擇CPU記錄配置 這四種模式官方文檔也有詳細說明。
1.對 Java 方法采樣:在應用的 Java 代碼執行期間,頻繁捕獲應用的調用堆棧。分析器會比較捕獲的數據集,以推導與應用的 Java 代碼執行有關的時間和資源使用信息。
基于采樣的跟蹤存在一個固有的問題,那就是如果應用在捕獲調用堆棧后進入一個方法并在下次捕獲前退出該方法,分析器將不會記錄該方法調用。如果您想要跟蹤生命周期如此短的方法,應使用插樁跟蹤。2.跟蹤 Java 方法:在運行時檢測應用,從而在每個方法調用開始和結束時記錄一個時間戳。系統會收集并比較這些時間戳,以生成方法跟蹤數據,包括時間信息和 CPU 使用率。
請注意,與檢測每個方法相關的開銷會影響運行時性能,并且可能會影響分析數據;對于生命周期相對較短的方法,這一點更為明顯。此外,如果應用在短時間內執行大量方法,則分析器可能很快就會超出其文件大小限制,因而不能再記錄更多跟蹤數據。3.對 C/C++ 函數采樣:捕獲應用的原生線程的采樣跟蹤數據。如需使用此配置,您必須將應用部署到搭載 Android 7.0(API 級別 24)或更高版本的設備上。
在內部,此配置使用 simpleperf 跟蹤應用的原生代碼。如果需為 simpleperf 指定其他選項,如對特定設備 CPU 采樣或指定高精度采樣持續時間,您可以從命令行使用 simpleperf。-
4.跟蹤系統調用:捕獲非常翔實的細節,以便您檢查應用與系統資源的交互情況。您可以檢查線程狀態的確切時間和持續時間、直觀地查看所有內核的 CPU 瓶頸在何處,并添加需分析的自定義跟蹤事件。當您排查性能問題時,此類信息至關重要。如需使用此配置,您必須將應用部署到搭載 Android 7.0(API 級別 24)或更高版本的設備上。
使用此跟蹤配置時,您可以通過檢測代碼,在分析器時間軸上直觀地標記重要的代碼例程。如需檢測 C/C++ 代碼,請使用由 trace.h 提供的原生跟蹤 API。如需檢測 Java 代碼,請使用 Trace 類。如需了解詳情,請參閱檢測您的應用代碼。此跟蹤配置建立在 systrace 的基礎之上。您可以使用 systrace 命令行實用程序指定除 CPU 性能剖析器提供的選項之外的其他選項。systrace 提供的其他系統級數據可幫助您檢查原生系統進程并排查丟幀或幀延遲問題。
-
設置好了之后就啟動Profile。
啟動Profile -
當你看到自己APP,CPU的使用率比較低的時候,差不多就是啟動完成了,點一下stop。
在這里插入圖片描述
3.2 啟動耗時分析
-
Call Chart 雙擊要看的線程,就能看到從上到下,方法執行的時長,除了系統的方法,綠色是自己的代碼,就能看到耗時了,這里的方法是按時間線排列的,從啟動到完成的過程。
Call Chart -
Top Down標簽顯示一個調用列表,在該列表中展開方法或函數節點會顯示它的被調用方。下圖可以看到我在自定義View里面放了一個Thread.sleep,休眠了3秒。
Top Down -
Flame Chart火焰圖橫向代表方法時長,向上就是被調用的方法,我們也能看到自定義View里面的sleep明顯比其他長。
Flame Chart
3.3 使用Debug Api 生成.trace文件
- 在Application onCreate 方法加入 Debug.startMethodTracing()。
- 在MainActivitu onWindowFocusChanged(boolean hasFocus) 方法加入 Debug.stopMethodTracing()。
public class BaoApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
Debug.startMethodTracing("baoTest");
}
}
public class MainActivity extends AppCompatActivity {
.
.
.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
.
.
.
}
/**
* MainActivity 停止啟動分析的地方
* @param hasFocus
*/
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
Debug.stopMethodTracing();
}
}
- 默認在自己應用的目錄下生成 .trace 文件,復制到自己電腦目錄下。
.trace文件目錄 -
拖到Android Studio,就可以查看結果了。
拖進去分析
4.StrictMode嚴苛模式
- 開發時開啟嚴苛模式,提示我們。
@Override
public void onCreate() {
super.onCreate();
if (BuildConfig.DEBUG) {
//線程檢測
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectDiskReads()
.detectDiskWrites()
.detectNetwork()
.penaltyLog()
.build());
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
.detectLeakedSqlLiteObjects()//數據庫對象泄漏
.detectLeakedClosableObjects()//未關閉的對象泄漏
.penaltyDeath()//違規奔潰
.penaltyLog()//違規日志
.build());
}
}
5.結尾
- 簡化布局,布局層級不要太多可以提高啟動速度(熟練使用約束布局可以減少層級),啟動和主線程不要做耗時操作。
- 啟動盡量別搞什么sleep休眠之類的,就算不報錯,但也不好查找。
- 有的APP會有啟動廣告,我們可以在展示廣告的時間里,利用子線程繼續初始化工作。
- 啟動的流程非常的多,也非常復雜,一般我們能改的就是自己的APP,通過工具分析自己的APP哪些地方比較耗時,能減少的盡量減少,有一些減少非常有限,但是項目比較大的時候,往往都是積少成多的,需要一點點去優化。