Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android Activity為什麼要細化出onCreate、onStart、onResume、onPause、onStop、onDesdroy這麼多方法讓應用去重載?

Android Activity為什麼要細化出onCreate、onStart、onResume、onPause、onStop、onDesdroy這麼多方法讓應用去重載?

編輯:關於Android編程

Android Activity為什麼要細化出onCreate、onStart、onResume、onPause、onStop、onDesdroy這麼多方法讓應用去重載?

 

 

最近在研究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

當觸發從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

 

先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()操作,即使這裡面有些比較耗時的操作,也沒有關系,這是在後台執行所以也不影響用戶的體驗。



  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved