Android Activity为什么要细化出onCreate、onStart、onResume、onPause、onStop、onDesdroy这么多方法让应用去重载?
原創(chuàng)鏈接:http://blog.csdn.net/zhao_3546/article/details/12843477,轉(zhuǎn)載請(qǐng)注明,謝謝。
最近在研究Activity的啟動(dòng)流程,老羅的blog在看,也找了其它資料學(xué)習(xí),也跟過Android4.3的源碼,
在跟代碼的過程中,突然想到下面的這個(gè)問題:
? ? Android Activity為什么要細(xì)化出onCreate、onStart、onResume、onPause、onStop、onDesdroy這么多方法讓應(yīng)用去重載?
網(wǎng)上太多根據(jù)Android開發(fā)規(guī)范翻譯轉(zhuǎn)載的內(nèi)容,都不是我想要的答案,那就自己分析下。
如下是一段典型的Activity間切換的日志,從AActivity切換到BActivity:
10-17 20:54:42.247: I/com.example.servicetest.AActivity(5817): onCreate() 1166919192 taskID=66 10-17 20:54:42.263: I/com.example.servicetest.AActivity(5817): onStart() 1166919192 taskID=66 10-17 20:54:42.263: I/com.example.servicetest.AActivity(5817): onResume() 1166919192 taskID=66 10-17 20:54:46.997: I/com.example.servicetest.AActivity(5817): onPause() 1166919192 taskID=66 10-17 20:54:47.021: I/com.example.servicetest.BActivity(5817): onCreate() 1166971824 taskID=66 10-17 20:54:47.028: I/com.example.servicetest.BActivity(5817): onStart() 1166971824 taskID=66 10-17 20:54:47.028: I/com.example.servicetest.BActivity(5817): onResume() 1166971824 taskID=66 10-17 20:54:47.099: I/com.example.servicetest.AActivity(5817): onStop() 1166919192 taskID=66
當(dāng)觸發(fā)從AActivity切換到BActivity時(shí)的日志如下:
10-17 20:54:46.997: I/com.example.servicetest.AActivity(5817): onPause()?1166919192 taskID=66
10-17 20:54:47.021: I/com.example.servicetest.BActivity(5817): onCreate()?1166971824 taskID=66
10-17 20:54:47.028: I/com.example.servicetest.BActivity(5817): onStart()?1166971824 taskID=66
10-17 20:54:47.028: I/com.example.servicetest.BActivity(5817): onResume()?1166971824 taskID=66
10-17 20:54:47.099: I/com.example.servicetest.AActivity(5817): onStop()?1166919192 taskID=66
先AActivity的onPause()被調(diào)用,然后是BActivity的初始化流程(onCreate() -->?onStart() -->?onResume()),再然后是AActivity的onStop()被調(diào)用。
有點(diǎn)意思,為什么不是先AActivity的onPause()、onStop()被調(diào)用,然后再BActivity的初始化流程(onCreate() -->?onStart() -->?onResume())?
或者又為什么不是先BActivity的初始化流程(onCreate() -->?onStart() -->?onResume()),再AActivity的onPause()、onStop()被調(diào)用?
如果所有的初始化都在onCreate()中實(shí)現(xiàn),會(huì)有什么問題?
? ? 首先,Activity的onCreate()被調(diào)用時(shí),Activity還不可見,如果要做一些動(dòng)畫,既然視圖還不存在,在onCreate中來啟動(dòng)動(dòng)畫,明顯有問題;
? ? 其次,AActivity 切換到 BActivity,再切換到 AActivity(我們假定是AActivity的同一個(gè)實(shí)例),由于實(shí)例已經(jīng)存在,所以onCreate不會(huì)再被調(diào)用,那AActivity從后臺(tái)切換至前臺(tái)時(shí),有可能需要一些初始化,那就沒法再被調(diào)用到了,也有問題;
如果所有的初始化都在onStart()中實(shí)現(xiàn),會(huì)有什么問題?
? ? 首先,onCreate()注釋中,是明確建議?setContentView()、findViewById()?要在?onCreate() 中被調(diào)用,但我實(shí)測(cè)了一下,在onStart()中調(diào)用?setContentView()、findViewById() 功能也是正常的;
? ? 其次,onStart() 被調(diào)用時(shí),Activity可能是可見了,但還不是可交互的,onResume()的注釋中都明確地說了這不是Activity對(duì)用戶是可見的最好的指示器,onStart() 在這之前被調(diào)用,那有一些特殊的初始化相關(guān)的邏輯在這里被調(diào)用也會(huì)有問題。
如果把所有的去初始化都在onStop()中實(shí)現(xiàn),會(huì)有什么問題?
??? 1、 在?onResume()?的注釋中,建議是在onResume()中打開獨(dú)占設(shè)備(比如相機(jī)),與onResume()對(duì)應(yīng)的是onPause(),所以所有的去初始化操作放在onStop()中執(zhí)行,可能會(huì)引出新的問題;
??? 2、onStop()?的注釋中明確地寫了,在內(nèi)存不足而導(dǎo)致系統(tǒng)無法保留此進(jìn)程的情況下,onStop() 可能都不會(huì)被執(zhí)行。
??? 我的老Android手機(jī)的相機(jī)應(yīng)用如果未正常關(guān)閉,相機(jī)在不重啟系統(tǒng)的情況下就無法再正常啟動(dòng),估計(jì)就和這個(gè)機(jī)制有關(guān);相機(jī)進(jìn)程是被強(qiáng)制殺掉的,而導(dǎo)致去初始化操作未被正常執(zhí)行。
?
Activity間跳轉(zhuǎn)時(shí),為什么是先AActivity的onPause()被調(diào)用,然后是BActivity的初始化流程(onCreate() -->?onStart() -->?onResume()),再然后是AActivity的onStop()被調(diào)用?
??? 1、在?onResume()?的注釋中,建議是在onResume()中打開獨(dú)占設(shè)備(比如相機(jī)),與onResume()對(duì)應(yīng)的是onPause(),關(guān)閉相機(jī)的操作也應(yīng)該在此方法中被調(diào)用;否則,考慮一下如下場(chǎng)景:
??????? 如果AActivity打開了相機(jī),我們點(diǎn)擊某按鈕要跳轉(zhuǎn)到BActivity中,BActivity也想打開相機(jī);假設(shè)AActivity的onPause() 在 BActivity啟動(dòng)后再被調(diào)用,
??????? 那BActivity根本就無法再正常啟動(dòng)相機(jī)。
??? 2、onPause() 的注釋中,也明確地說了,在這個(gè)方法中執(zhí)行停止動(dòng)畫等比較耗CPU的操作,如果不先執(zhí)行這些操作,就先啟動(dòng)新應(yīng)用,然后再來執(zhí)行此操作,確實(shí)是不合邏輯;
?
從AActivity切換到BActivity的日志如下:
10-17 20:54:46.997: I/com.example.servicetest.AActivity(5817): onPause()?1166919192 taskID=66
10-17 20:54:47.021: I/com.example.servicetest.BActivity(5817): onCreate()?1166971824 taskID=66
10-17 20:54:47.028: I/com.example.servicetest.BActivity(5817): onStart()?1166971824 taskID=66
10-17 20:54:47.028: I/com.example.servicetest.BActivity(5817): onResume()?1166971824 taskID=66
10-17 20:54:47.099: I/com.example.servicetest.AActivity(5817): onStop()?1166919192 taskID=66
從邏輯的完整性和用戶體驗(yàn)的角度來分析,這樣實(shí)現(xiàn)確實(shí)是比較合理的,當(dāng)用戶觸發(fā)某事件切換到新的Activity,用戶肯定是想盡快進(jìn)入新的視圖進(jìn)行操作,
上面已經(jīng)說了,在onResume()一般會(huì)打開獨(dú)占設(shè)備,開啟動(dòng)畫等,
當(dāng)需要從AActivity切換到BActivity時(shí),先執(zhí)行AActivity中的與onResume()相對(duì)應(yīng)的onPause()操作,比如關(guān)閉獨(dú)占設(shè)備,關(guān)閉動(dòng)畫,或其它耗費(fèi)cpu的操作;
以防止BActivity也需要使用這些資源,關(guān)閉耗CPU的操作,也有利于BActivity運(yùn)行的流暢。
底層執(zhí)行AActivity的onPause()時(shí),有一定的時(shí)間限制的,當(dāng)ActivityManagerService通知應(yīng)用進(jìn)程暫停指定的Activity時(shí),如果對(duì)應(yīng)的onPause()在500ms內(nèi)還沒有執(zhí)行完,ActivityManagerService就會(huì)強(qiáng)制關(guān)閉這個(gè)Activity。如下就是對(duì)應(yīng)的onPause()執(zhí)行超時(shí)常量定義:
// How long we wait until giving up on the last activity to pause. This// is short because it directly impacts the responsiveness of starting the// next activity.static final int PAUSE_TIMEOUT = 500; // 定義在ActivityStack.java中
AActivity中比較消耗資源的部分關(guān)閉后,再切換到BActivity中執(zhí)行BActivity的初始化,顯示BActivity中的View。
當(dāng)BActivity已經(jīng)執(zhí)行顯示出來了,用戶可以交互,后臺(tái)再去執(zhí)行AActivity的onStop()操作,即使這里面有些比較耗時(shí)的操作,也沒有關(guān)系,這是在后臺(tái)執(zhí)行所以也不影響用戶的體驗(yàn)。
總結(jié)
以上是生活随笔為你收集整理的Android Activity为什么要细化出onCreate、onStart、onResume、onPause、onStop、onDesdroy这么多方法让应用去重载?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Utils.toDip()的用法
- 下一篇: network: Android 网络判