2011-12-26 68 views
3

活動生命週期令我頭疼。 http://developer.android.com/reference/android/app/Activity.html的文檔在描述可見性的概念時非常模糊,我不知道onStop()被調用的時間與onPause()的時間有關。「可見性」在「活動生命週期」中指的是什麼? onPause vs onStop?

比較下列兩個語句從文檔:

(右拍攝的生命週期圖表下方)

onStart()onStop()方法可以被調用多次,如 的活性變得可見並隱藏給用戶。

VS

(藍色表進一步打倒 「killable」 列)

onPause()當系統即將開始恢復以前的活動調用。

我從第一次報價明白了什麼,是onStop()被稱爲上的活動AA爲「隱藏」。 「隱藏」我想是指當另一個活動B已被恢復,並完全覆蓋活動A。 但是第二個報價表明當另一個活動即將開始恢復時,將調用onPause()。這不會完全隱藏活動A嗎?這兩種情況都似乎意味着那個活動A變得「隱藏」了,不是嗎?根據我可能的錯誤解釋,在相同的情況下調用onPause()onStop()

隱藏文檔(onStop()被調用)和部分可見性(onPause()被調用)之間似乎也有所不同。但是什麼時候活動仍然部分可見?他們的意思是字面意思嗎?或者,當一個活動啓動了一個覆蓋整個屏幕的新活動(活動調用startActivityForResult並啓動日期選擇器活動)時,它仍然可以被視爲「部分可見」?當然,活動不會在onStop調用?它應該會在任何時候收到結果!

所以我想弄清楚我沒有得到什麼。 我知道打電話給onPause是有保證的。當活動A失去焦點(設備進入睡眠模式,屏幕鎖定等)時,活動B採取前景(其中活動B可能已經或可能未被活動A啓動)。 但是在哪一點上是在活動A上調用onStop()

是否在活動堆棧的活動A上堆積了多少活動?遊戲中有兩種不同的「可視性」定義嗎?

對不起文本牆,但我真的很沮喪:S

所以問題表示:正是在這種情況下,是一個活動視爲「隱藏」,使得onStop()叫上了嗎?

編輯:

我插入Toast通知在每個ONX方法,並發現了一些額外的怪事:

  1. 按下Home鍵將總是調用的onStop()。但啓動應用程序不會調用onRestart()。相反,它調用onCreate()。這對我來說似乎很陌生,但好吧...
  2. 當在主要活動之上啓動「USB Mass Storage」活動時,調用onStop()。當退出USB存儲活動時,返回到主要活動onRestart()被調用,而不是onCreate()
  3. 當設備進入睡眠模式並且被喚醒時,活動只會經歷onPause()onResume()循環。

最後一點是期待的(雖然我不能讓它適應生命週期圖)。但最新的1.和2.?

第一點,我期待在再次開始活動時撥打onRestart()。爲什麼要取消分配活動並改爲撥打onCreate()

然後看看第2點: 根據文檔:當「另一項活動出現在活動前面」時,應該調用onPaused()。 USB存儲活動出現時發生的情況不是這樣嗎?它沒有叫onPause(),它經歷了onStop() - OnRestart()週期!很顯然,文件並不認爲「另一項活動出現在活動前」的情況。那麼究竟發生了什麼?

+0

你提到,你將不能夠相信日誌,因爲可能的onStop不被調用。只有在Android對資源至關重要並且決定需要您的Activity正在使用的資源的極端情況下,纔會發生這種情況。大部分時間你都可以信任日誌。 – Juan 2011-12-27 07:04:32

+0

根據文檔,活動資源的釋放將首先發生onStop或onPause被調用(在onPause之後解除分配是一種非常罕見的情況)。從圖中暫停到停止的轉換觸發器是「活動不再可見」。所以它似乎不適合你的帖子。 – uhmdown 2011-12-27 10:04:17

+0

我可能誤解了你的帖子,胡安。也許你只是指在onPause之後執行取消分配的情況。但是,日誌記錄可能會告訴我什麼時候在個別情況下調用onStop,但它不會讓我全面瞭解何時應該或不應該調用onStop。 – uhmdown 2011-12-27 11:26:16

回答

2

好吧,我想我現在已經得到了這個。

1.

的關鍵,第一點是這個鏈接:

http://code.google.com/p/android/issues/detail?id=2373

它的錯誤。 Theres中的一些代碼已經完全解決了創建新根活動實例的問題,而不是僅僅重啓最後一個活動活動(在home按鈕被按下之前)。

我把代碼在onCreate方法的頂部,略低於super.onCreate電話:

if (!isTaskRoot()) { 
    final Intent intent = getIntent(); 
    final String intentAction = intent.getAction(); 
    if (intent.hasCategory(Intent.CATEGORY_LAUNCHER) && 
      intentAction != null && intentAction.equals(Intent.ACTION_MAIN)) { 
     finish(); return; 
    } 
} 

注意,我完成後添加return語句使onCreate方法的其餘部分不在檢測到錯誤的情況下運行。

2. & 3。

到第二點和第三點的關鍵是這兩個環節:

http://answers.oreilly.com/topic/2692-android-programming-understanding-the-activity-life-cycle/

How to make Activity, not covering full screen

事實證明,「知名度」確實是名副其實!因此,當文檔說「另一項活動出現在活動前面」時,碰撞活動背後的活動仍然部分可見。這意味着Android活動管理器必須檢查碰撞的活動是否是全屏活動:如果是,則前一活動調用onStop()。如果不是,則在前一個活動上調用onPaused()

這簡單解釋了爲什麼USB存儲管理器導致調用onStop()

這也意味着當設備進入睡眠模式時,活動管理器認爲它是非全屏活動,即使技術上主要活動完全隱藏在它後面。

(參見如何使非全屏活動的第二個鏈接)

有趣的是,在下拉窗口(與通知)不會調用onPause()(也不叫onStop()),即使它作爲非全屏活動會有意義。這一定是我會自己調查的某種例外。

這也意味着onStop()-onRestart()週期可能比onPause()-onResume()週期更普遍(儘管兩者都必須被考慮),因爲活動可能更多是全屏活動(個人而言,我認爲文檔指出相反:onPause-onResume更通用,但也許這就是我)。

此外,這意味着當主活動爲結果啓動新的全屏活動時,主活動將首先停止,並在結果檢索活動完成後重新啓動。

所以現在唯一的問題是如何最好地處理被暫停的活動(意味着它被非全屏活動所覆蓋)並被釋放(儘管這種情況很罕見)。可能會遇到什麼挑戰?

但是,這超出了這個問題的範圍。

+0

你有沒有發現任何關於狀態欄下拉如何不觸發onPause()? – 2012-04-08 23:05:23

+1

不是。我剛剛接受它作爲一個特例。我想它並不是生活在活動生命週期框架中,而是簡單地繞過它。從某種意義上說,它與當前活動沒有任何互動,因爲它只是檢查通知的一個快速覆蓋圖,所以我只是將它留在那裏。 – uhmdown 2012-05-03 14:38:44

+0

如果我決定鑽研AOSP並找到答案,我會在這裏發表快速評論。 – 2012-05-03 14:48:08