您好,登錄后才能下訂單哦!
小編給大家分享一下android性能優(yōu)化之啟動(dòng)過程的示例分析,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
一、應(yīng)用的啟動(dòng)方式
通常來說,啟動(dòng)方式分為兩種:冷啟動(dòng)和熱啟動(dòng)。
1、冷啟動(dòng):當(dāng)啟動(dòng)應(yīng)用時(shí),后臺(tái)沒有該應(yīng)用的進(jìn)程,這時(shí)系統(tǒng)會(huì)重新創(chuàng)建一個(gè)新的進(jìn)程分配給該應(yīng)用,這個(gè)啟動(dòng)方式就是冷啟動(dòng)。
2、熱啟動(dòng):當(dāng)啟動(dòng)應(yīng)用時(shí),后臺(tái)已有該應(yīng)用的進(jìn)程(例:按back鍵、home鍵,應(yīng)用雖然會(huì)退出,但是該應(yīng)用的進(jìn)程是依然會(huì)保留在后臺(tái),可進(jìn)入任務(wù)列表查看),所以在已有進(jìn)程的情況下,這種啟動(dòng)會(huì)從已有的進(jìn)程中來啟動(dòng)應(yīng)用,這個(gè)方式叫熱啟動(dòng)。
特點(diǎn)
1、冷啟動(dòng):冷啟動(dòng)因?yàn)橄到y(tǒng)會(huì)重新創(chuàng)建一個(gè)新的進(jìn)程分配給它,所以會(huì)先創(chuàng)建和初始化Application類,再創(chuàng)建和初始化MainActivity類(包括一系列的測(cè)量、布局、繪制),最后顯示在界面上。
2、熱啟動(dòng):熱啟動(dòng)因?yàn)闀?huì)從已有的進(jìn)程中來啟動(dòng),所以熱啟動(dòng)就不會(huì)走Application這步了,而是直接走M(jìn)ainActivity(包括一系列的測(cè)量、布局、繪制),所以熱啟動(dòng)的過程只需要?jiǎng)?chuàng)建和初始化一個(gè)MainActivity就行了,而不必創(chuàng)建和初始化Application,
因?yàn)橐粋€(gè)應(yīng)用從新進(jìn)程的創(chuàng)建到進(jìn)程的銷毀,Application只會(huì)初始化一次。
二、應(yīng)用的啟動(dòng)過程
冷啟動(dòng)啟動(dòng)流程:當(dāng)點(diǎn)擊app的啟動(dòng)圖標(biāo)時(shí),安卓系統(tǒng)會(huì)從Zygote進(jìn)程中fork創(chuàng)建出一個(gè)新的進(jìn)程分配給該應(yīng)用,之后會(huì)依次創(chuàng)建和初始化Application類、創(chuàng)建MainActivity類、加載主題樣式Theme中的
windowBackground等屬性設(shè)置給MainActivity以及配置Activity層級(jí)上的一些屬性、再inflate布局、當(dāng)onCreate/onStart/onResume方法都走完了后最后才進(jìn)行contentView的measure/layout/draw顯示在界面上,所以直到這里,
應(yīng)用的第一次啟動(dòng)才算完成,這時(shí)候我們看到的界面也就是所說的第一幀。所以,總結(jié)一下,應(yīng)用的啟動(dòng)流程如下:
Application的構(gòu)造器方法——>attachBaseContext()——>onCreate()——>Activity的構(gòu)造方法——>onCreate()——>配置主題中背景等屬性——>onStart()——>onResume()——>測(cè)量布局繪制顯示在界面上。
大致流程如下:
1、點(diǎn)擊桌面圖標(biāo),Launcher會(huì)啟動(dòng)程序默認(rèn)的Acticity,之后再按照程序的邏輯啟動(dòng)各種Activity
2、啟動(dòng)Activity都需要借助應(yīng)用程序框架層的ActivityManagerService服務(wù)進(jìn)程(Service也是由ActivityManagerService進(jìn)程來啟動(dòng)的);在Android應(yīng)用程序框架層中,ActivityManagerService是一個(gè)非常重要的接口,
它不但負(fù)責(zé)啟動(dòng)Activity和Service,還負(fù)責(zé)管理Activity和Service。
Step 1. 無論是通過Launcher來啟動(dòng)Activity,還是通過Activity內(nèi)部調(diào)用startActivity接口來啟動(dòng)新的Activity,都通過Binder進(jìn)程間通信進(jìn)入到ActivityManagerService進(jìn)程中,并且調(diào)用ActivityManagerService.startActivity接口;
Step 2. ActivityManagerService調(diào)用ActivityStack.startActivityMayWait來做準(zhǔn)備要啟動(dòng)的Activity的相關(guān)信息;
Step 3. ActivityStack通知ApplicationThread要進(jìn)行Activity啟動(dòng)調(diào)度了,這里的ApplicationThread代表的是調(diào)用ActivityManagerService.startActivity接口的進(jìn)程,對(duì)于通過點(diǎn)擊應(yīng)用程序圖標(biāo)的情景來說,這個(gè)進(jìn)程就是Launcher了,
而對(duì)于通過在Activity內(nèi)部調(diào)用startActivity的情景來說,這個(gè)進(jìn)程就是這個(gè)Activity所在的進(jìn)程了;
Step 4. ApplicationThread不執(zhí)行真正的啟動(dòng)操作,它通過調(diào)用ActivityManagerService.activityPaused接口進(jìn)入到ActivityManagerService進(jìn)程中,看看是否需要?jiǎng)?chuàng)建新的進(jìn)程來啟動(dòng)Activity;
Step 5. 對(duì)于通過點(diǎn)擊應(yīng)用程序圖標(biāo)來啟動(dòng)Activity的情景來說,ActivityManagerService在這一步中,會(huì)調(diào)用startProcessLocked來創(chuàng)建一個(gè)新的進(jìn)程,而對(duì)于通過在Activity內(nèi)部調(diào)用startActivity來啟動(dòng)新的Activity來說,這一步是不需要執(zhí)行的,
因?yàn)樾碌腁ctivity就在原來的Activity所在的進(jìn)程中進(jìn)行啟動(dòng);
Step 6. ActivityManagerServic調(diào)用ApplicationThread.scheduleLaunchActivity接口,通知相應(yīng)的進(jìn)程執(zhí)行啟動(dòng)Activity的操作;
Step 7. ApplicationThread把這個(gè)啟動(dòng)Activity的操作轉(zhuǎn)發(fā)給ActivityThread,ActivityThread通過ClassLoader導(dǎo)入相應(yīng)的Activity類,然后把它啟動(dòng)起來。
三、冷啟動(dòng)過程中碰到的白屏黑屏以及優(yōu)化啟動(dòng)時(shí)間
1、白屏問題 :
android studio升級(jí) 2.0之后 加上Instant Run,Instant Run為了能夠讓我們快速部署代碼,背后其實(shí)是有一套非常復(fù)雜的邏輯的,比如要在APK中建立服務(wù)器與Android Studio進(jìn)行通信,以及代碼差異比對(duì)和替換等,在研發(fā)過程中可能出現(xiàn)白屏問題,
一般release版的程序是不會(huì)出現(xiàn)這種現(xiàn)象的;
如果接下來還會(huì)出現(xiàn)白屏問題,可以查看style文件
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> ...... <item name="android:windowIsTranslucent">true</item> <item name="android:windowNoTitle">true</item> </style>
加入了兩個(gè)屬性,windowIsTranslucent和windowNoTitle,將這兩個(gè)屬性都設(shè)置成true,就可以讓程序在初始化的時(shí)候窗口是透明的,初始化結(jié)束后程序主界面才會(huì)顯示出來,從而也就完全看不到白屏界面了
2、啟動(dòng)時(shí)間的優(yōu)化
先測(cè)量activity的啟動(dòng)時(shí)間-------Activity的reportFullyDrawn()方法
你就需要調(diào)用Activity的reportFullyDrawn()。它將在log里報(bào)告從apk初始化(和前面Displayed的時(shí)間是一樣的)到reportFullyDrawn() 方法被調(diào)用用了多長(zhǎng)時(shí)間。
reportFullyDrawn()方法顯示的log也是類似這樣:
ActivityManager: Displayed com.Android.myexample/.StartupTiming: +768ms
在4.4上調(diào)用reportFullyDrawn()方法會(huì)崩潰(但是log還是能正常打?。崾拘枰猆PDATE_DEVICE_STATS權(quán)限 ,但是這個(gè)權(quán)限只有系統(tǒng)app才能授權(quán)。解決的辦法是這樣調(diào)
try{ reportFullyDrawn(); }catch(SecurityException e){ }
還有一種測(cè)量啟動(dòng)時(shí)間的方法也值得一提,那就是screenrecord命令
首先啟動(dòng)帶—bugreport選項(xiàng)(它可以在frames 中添加時(shí)間戳-應(yīng)該是L中的特性)的screenrecord 命令:
$ adb shell screenrecord --bugreport /sdcard/launch.mp4
然后點(diǎn)擊app的圖標(biāo),等待app顯示,ctrl-C screenrecord, 使用adb pull命令把文件導(dǎo)出到電腦。
$ adb pull /sdcard/launch.mp4
現(xiàn)在你可以打開錄制視頻看看發(fā)生了什么。你需要一個(gè)能逐幀查看的視頻播放器(mac上的Quicktime 就可以,不清楚其它os上什么播放器這個(gè)功能最好使)?,F(xiàn)在逐幀播放,注意視頻的上方有一個(gè)frame 時(shí)間戳。
一直往前直到你發(fā)現(xiàn)app圖標(biāo)高亮了為止。這個(gè)時(shí)候系統(tǒng)已經(jīng)處理了圖標(biāo)上的點(diǎn)擊事件,開始啟動(dòng)app了,記錄下這一幀的時(shí)間。繼續(xù)播放幀直到你看到了app整個(gè)UI的第一幀為止。根據(jù)不同情況(是否有啟動(dòng)窗口,是否有啟動(dòng)畫面等等),
事件和窗口發(fā)生的實(shí)際順序可能會(huì)有不同。對(duì)于一個(gè)簡(jiǎn)單的app來說,你會(huì)首先見到啟動(dòng)窗口,然后漸變出app真實(shí)的UI。在你看到UI上的任何內(nèi)容之后,你應(yīng)該記錄下第一幀,這時(shí)app完成了布局和繪制,準(zhǔn)備開始顯示出來了。同時(shí)也記錄下這一幀所發(fā)生的時(shí)間。
現(xiàn)在把這兩個(gè)時(shí)間相減 ((UI displayed) - (icon tapped)); 得到app從點(diǎn)擊到繪制就緒的所有時(shí)間。雖然這個(gè)時(shí)間包含了進(jìn)程啟動(dòng)之前的時(shí)間,但是至少它可以用于跟其他app比較。
Android冷啟動(dòng)時(shí)間優(yōu)化
冷啟動(dòng)時(shí)間是指當(dāng)用戶點(diǎn)擊你的app那一刻到系統(tǒng)調(diào)用Activity.onCreate()之間的時(shí)間段。在這個(gè)時(shí)間段內(nèi),WindowManager會(huì)先加載app主題樣式中的windowBackground做為app的預(yù)覽元素,然后再真正去加載activity的layout布局
冷啟動(dòng)時(shí)間優(yōu)化
知道了Android冷啟動(dòng)時(shí)間的原理之后,就可以通過一些小技巧來對(duì)冷啟動(dòng)時(shí)間進(jìn)行優(yōu)化,從而讓你app加載變得”快“一些(視覺體驗(yàn)上的快)。我們可制作一個(gè)啟動(dòng)Activity的背景樣式的.9圖片,然后把這個(gè).9圖片做為windowBackground。
圖片制作好之后,我們就可以用它做為app冷啟動(dòng)階段的預(yù)覽元素,如下設(shè)置:
為啟動(dòng)的Activity自定義一個(gè)Theme
<style name="AppTheme.Launcher"> <item name="android:windowBackground">@drawable/window_background_statusbar_toolbar_tab</item> </style>
將新的Theme應(yīng)用到設(shè)置到AndroidManifest.xml中
<activity android:name=".MainActivity" android:theme="@style/AppTheme.Launcher"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
由于給MainActivity設(shè)置了一個(gè)新的Theme,這樣做會(huì)覆蓋原來的Theme,所以在MainActivity中需要設(shè)置回原來的Theme
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { // Make sure this line comes before calling super.onCreate(). setTheme(R.style.AppTheme); super.onCreate(savedInstanceState); } }
以上是“android性能優(yōu)化之啟動(dòng)過程的示例分析”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。