【Android 性能优化】应用启动优化 ( 安卓应用启动分析 | Launcher 应用启用普通安卓应用 | 应用进程分析 )
文章目錄
- 一、 Launcher 應用 startActivitySafely 方法分析
- 二、 Launcher 中的 startActivity(View v, Intent intent, Object tag) 方法分析
- 三、 Android 應用進程分析
上一篇博客 【Android 性能優化】應用啟動優化 ( 安卓應用啟動分析 | Launcher 應用簡介 | Launcher 應用源碼簡介 | Launcher 應用快捷方式圖標點擊方法分析 ) 分析了 Launcher 應用中 Launcher.java 界面代碼 , 并分析了圖標點擊事件 onClick 方法 , 本篇博客繼續分析 Launcher 應用中啟動普通 Android 應用的源碼 ;
一、 Launcher 應用 startActivitySafely 方法分析
在 Launcher 應用中 , 點擊快捷方式圖標 , 調用 onClick 方法 , 如果判定點擊的圖標組件時應用圖標 , 會觸發調用 startActivitySafely 方法 , 啟動該圖標對應的 Android 應用 Activity 界面 ;
boolean startActivitySafely(View v, Intent intent, Object tag) {boolean success = false;try {// 啟動新的應用success = startActivity(v, intent, tag);} catch (ActivityNotFoundException e) {Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();Log.e(TAG, "Unable to launch. tag=" + tag + " intent=" + intent, e);}return success;}該段代碼在 \packages\apps\Launcher2\src\com\android\launcher2\Launcher.java 界面中定義 , 該界面是 Launcher 應用的主界面 ;
二、 Launcher 中的 startActivity(View v, Intent intent, Object tag) 方法分析
1 . Launcher 中的啟動方法 : Launcher 應用中啟動 Android 應用 , 調用 startActivity(View v, Intent intent, Object tag) 方法 , 在該方法中 , 啟動 Android 應用的啟動 Activity ;
3 . 實際啟動方法 : 在 startActivity(View v, Intent intent, Object tag) 方法中啟動 Android 應用的核心方法是 startActivity(intent, opts.toBundle()) 和 startActivity(intent) 啟動安卓應用界面 ;
( 該 startActivity(intent) 方法就是我們經常調用的啟動界面的方法 )
4 . Intent 來源 : 該啟動 的 Intent 參數是之前 onClick 方法中從 Launcher 中的圖標組件中獲取的 Tag 標簽 ;
public void onClick(View v) {// 該從 View v 組件中獲取的標簽 Tag 就是 IntentObject tag = v.getTag();if (tag instanceof ShortcutInfo) {// 獲取 Intent 對象 , 可以直接根據該對象啟動應用 Activity 界面final Intent intent = ((ShortcutInfo) tag).intent;} }5 . Launcher 應用中 startActivity(View v, Intent intent, Object tag) 方法源碼 :
boolean startActivity(View v, Intent intent, Object tag) {// 設置一個啟動標志// 查找當前任務棧中是否有與該 Activity 親和性相同的任務棧// 如果有將該任務棧移動到前臺 , 至于是創建新 Activity 還是復用原來 Activity , 按照該 Activity 的啟動模式進行操作// 如果沒有親和性相同任務棧 , 創建任務棧 , 移動到前臺intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);try {// Only launch using the new animation if the shortcut has not opted out (this is a// private contract between launcher and may be ignored in the future).boolean useLaunchAnimation = (v != null) &&!intent.hasExtra(INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION);UserHandle user = (UserHandle) intent.getParcelableExtra(ApplicationInfo.EXTRA_PROFILE);LauncherApps launcherApps = (LauncherApps)this.getSystemService(Context.LAUNCHER_APPS_SERVICE);if (useLaunchAnimation) {ActivityOptions opts = ActivityOptions.makeScaleUpAnimation(v, 0, 0,v.getMeasuredWidth(), v.getMeasuredHeight());if (user == null || user.equals(android.os.Process.myUserHandle())) {// Could be launching some bookkeeping activity// 根據 Intent 啟動點擊圖標對應的 Activity 界面startActivity(intent, opts.toBundle());} else {launcherApps.startMainActivity(intent.getComponent(), user,intent.getSourceBounds(),opts.toBundle());}} else {if (user == null || user.equals(android.os.Process.myUserHandle())) {// 真實啟動應用的方法// 根據 Intent 啟動點擊圖標對應的 Activity 界面startActivity(intent);} else {launcherApps.startMainActivity(intent.getComponent(), user,intent.getSourceBounds(), null);}}return true;} catch (SecurityException e) {Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();Log.e(TAG, "Launcher does not have the permission to launch " + intent +". Make sure to create a MAIN intent-filter for the corresponding activity " +"or use the exported attribute for this activity. "+ "tag="+ tag + " intent=" + intent, e);}return false;}該段代碼在 \packages\apps\Launcher2\src\com\android\launcher2\Launcher.java 界面中定義 , 該界面是 Launcher 應用的主界面 ;
三、 Android 應用進程分析
1 . 應用啟動前置操作 : 調用 startActivity(Intent intent) 方法 , 通過進程間通信 , 啟動另外的 Android 應用 , 首先會去查找該 Activity 對應的包名 , 為該應用分配內存空間 , 并加載新應用對應的 main 函數 , 通過 Zygote 進程 , 孵化出新進程 , 在新進程中有方法區 , 堆區 , 棧區 , 等內存分區 ;
2 . 創建新進程過程 : Launcher 應用與 Zygote 進程進行通信后 , 通知 Zygote 進程 fork 一個新的進程 , 該新進程中通過 System Server 執行 ActivityThread , 執行 ActivityThread 中的主函數 ;
該 ActivityThread 中的主函數 main 中 , 有一個 Looper 不停的在不停的輪詢讀取 MessageQueue 中的消息 , 用于接收指令執行應用相關操作 ;
3 . 創建進程依據 : 根據包名查找創建進程 ;
① 根據包名查找創建進程 : 這個 ActivityThread 是指定包名的應用的函數入口 , 不是一個隨意的入口 , 需要根據該包名查找對應的進程是否已經存在 ;
② 進程不存在 : 如果這個進程不存在 , 需要重新 fork 進程 , 執行后續一系列操作 , 那么這次啟動稱為冷啟動 ;
③ 進程存在 : 如果之前該包名對應的應用存在 , 不需要重新創建進程 , 進程可以直接復用 , 那么這次啟動稱為熱啟動 ;
4 . 從進程角度分析冷啟動與熱啟動 :
① 冷啟動 : 運行程序后 , 應用啟動 , 會為該應用啟動一個新進程 ; 這次啟動是冷啟動 ;
② 退出應用 進程保留 : 點擊回退鍵 , 應用退出 , 此時該進程進入后臺 , 不會馬上被殺死 ;
③ 熱啟動 : 再次啟動該應用時 , 就會重新啟用之前的進程 , 這次啟動就是熱啟動 ;
這也是安卓手機為什么越用越卡的原因 , 進程進入后臺 , 沒有及時殺死 ; 蘋果手機進程進入后臺 , 會放入一個與運行時不相關的內存中 ;
總結
以上是生活随笔為你收集整理的【Android 性能优化】应用启动优化 ( 安卓应用启动分析 | Launcher 应用启用普通安卓应用 | 应用进程分析 )的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Android 性能优化】应用启动优化
- 下一篇: 【Android 性能优化】应用启动优化