編輯:關於Android編程
最近在研究Activity的啟動流程,老羅的blog在看,也找了其它資料學習,也跟過Android4.3的源碼,
在跟代碼的過程中,突然想到下面的這個問題:
Android Activity為什麼要細化出onCreate、onStart、onResume、onPause、onStop、onDesdroy這麼多方法讓應用去重載?
網上太多根據Android開發規范翻譯轉載的內容,都不是我想要的答案,那就自己分析下。
如下是一段典型的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
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()被調用,然後是BActivity的初始化流程(onCreate() --> onStart() --> onResume()),再然後是AActivity的onStop()被調用。
有點意思,為什麼不是先AActivity的onPause()、onStop()被調用,然後再BActivity的初始化流程(onCreate() --> onStart() --> onResume())?
或者又為什麼不是先BActivity的初始化流程(onCreate() --> onStart() --> onResume()),再AActivity的onPause()、onStop()被調用?
如果所有的初始化都在onCreate()中實現,會有什麼問題?
首先,Activity的onCreate()被調用時,Activity還不可見,如果要做一些動畫,既然視圖還不存在,在onCreate中來啟動動畫,明顯有問題;
其次,AActivity 切換到 BActivity,再切換到 AActivity(我們假定是AActivity的同一個實例),由於實例已經存在,所以onCreate不會再被調用,那AActivity從後台切換至前台時,有可能需要一些初始化,那就沒法再被調用到了,也有問題;
如果所有的初始化都在onStart()中實現,會有什麼問題?
首先,onCreate()注釋中,是明確建議 setContentView()、findViewById() 要在 onCreate() 中被調用,但我實測了一下,在onStart()中調用 setContentView()、findViewById() 功能也是正常的;
其次,onStart() 被調用時,Activity可能是可見了,但還不是可交互的,onResume()的注釋中都明確地說了這不是Activity對用戶是可見的最好的指示器,onStart() 在這之前被調用,那有一些特殊的初始化相關的邏輯在這裡被調用也會有問題。
如果把所有的去初始化都在onStop()中實現,會有什麼問題?
1、 在 onResume() 的注釋中,建議是在onResume()中打開獨占設備(比如相機),與onResume()對應的是onPause(),所以所有的去初始化操作放在onStop()中執行,可能會引出新的問題;
2、onStop() 的注釋中明確地寫了,在內存不足而導致系統無法保留此進程的情況下,onStop() 可能都不會被執行。
我的老Android手機的相機應用如果未正常關閉,相機在不重啟系統的情況下就無法再正常啟動,估計就和這個機制有關;相機進程是被強制殺掉的,而導致去初始化操作未被正常執行。
Activity間跳轉時,為什麼是先AActivity的onPause()被調用,然後是BActivity的初始化流程(onCreate() --> onStart() --> onResume()),再然後是AActivity的onStop()被調用?
1、在 onResume() 的注釋中,建議是在onResume()中打開獨占設備(比如相機),與onResume()對應的是onPause(),關閉相機的操作也應該在此方法中被調用;否則,考慮一下如下場景:
如果AActivity打開了相機,我們點擊某按鈕要跳轉到BActivity中,BActivity也想打開相機;假設AActivity的onPause() 在 BActivity啟動後再被調用,
那BActivity根本就無法再正常啟動相機。
2、onPause() 的注釋中,也明確地說了,在這個方法中執行停止動畫等比較耗CPU的操作,如果不先執行這些操作,就先啟動新應用,然後再來執行此操作,確實是不合邏輯;
從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
從邏輯的完整性和用戶體驗的角度來分析,這樣實現確實是比較合理的,當用戶觸發某事件切換到新的Activity,用戶肯定是想盡快進入新的視圖進行操作,
上面已經說了,在onResume()一般會打開獨占設備,開啟動畫等,
當需要從AActivity切換到BActivity時,先執行AActivity中的與onResume()相對應的onPause()操作,比如關閉獨占設備,關閉動畫,或其它耗費cpu的操作;
以防止BActivity也需要使用這些資源,關閉耗CPU的操作,也有利於BActivity運行的流暢。
底層執行AActivity的onPause()時,有一定的時間限制的,當ActivityManagerService通知應用進程暫停指定的Activity時,如果對應的onPause()在500ms內還沒有執行完,ActivityManagerService就會強制關閉這個Activity。如下就是對應的onPause()執行超時常量定義:
// 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中比較消耗資源的部分關閉後,再切換到BActivity中執行BActivity的初始化,顯示BActivity中的View。
當BActivity已經執行顯示出來了,用戶可以交互,後台再去執行AActivity的onStop()操作,即使這裡面有些比較耗時的操作,也沒有關系,這是在後台執行所以也不影響用戶的體驗。
一.啟動動畫的漸變:以後可能會用到的啟動動畫的效果:效果圖: 主界面: public class MainActivity extends Activity {
首先我們先來看一下效果分析我們來看這個進度條應該分為3個小部分1.中間的圓2.外邊的圓環3.中間的文字分開畫這3部分就是需要我們自己畫出來的,因此我們需要3根畫筆//設置
簡介項目需要...直接展示效果吧:原理使用UGUI提供的ScrollRect和ScrollBar組件實現基本滑動以及自己控制每次移動一頁來達到滑頁的效果。實現過程1.創建
一、eclipse 中生成android keystore 建立任意一個android項目(例如:AntForAndroid) Export Signed Appl