天天看點

Android Activity生命周期和啟動模式

假如程式設計易懂得,那麼程式員就不會熱情地寫出注釋,也不會有得到程式設計的快樂。

這周六周日是在是太忙了,導緻部落格沒有及時更新,在這裡深表慚愧,是以這才加班加點完成一篇部落格來彌補我的過失,好了不說那麼多了,進入正題,今天主要講的是 Activity 的聲明周期和啟動模式,其實這兩個地方的基礎知識本篇不會介紹很多,本篇主要介紹的是我們在使用中遇到的問題,和我們在使用中正确的使用規則。

一、概述

       1、當我提起 Activity 的生命周期的時候,你會很容的回答出,onCreate 、onStart、onResume、onPause、onStop、onDestory 等一些回調方法,那每個回調中,我們應該做什麼事情,不應該做什麼事情或許你就很迷惑了,那今天我們在這篇文章中将會問你排憂解惑。

       2、Activity 的啟動模式在我看來也是一個很有意思的東西,我們可以通過設定 launchMode 這個屬性指定我們的 Activity 的啟動模式,我們通常的 Activity 啟動模式都是 standard ,有時候會用到 singleTop 和 singleTask,其實我認為最有意思的就是這個 singleInstance,那今天我們就來說說我們在使用這四種啟動模式遇到的問題。

二、Activity 生命周期

       2.1 正常情況下的聲明周期

             onCreate:

             這個方法其實不用我們多說了,一般隻會執行一次,就是進行一些初始化等操作,這個方法中有一個

      Bundle 值,這個值在我們正常啟動的時候會是空的,是以我們判斷是否為正常啟動就判斷一些這個 Bundle是否         為空就可以了。

             onStart:

             當回調這個方法的時候,說明我們的 Activity 已經可見了,但是還沒有出現在前台,你可以這樣了解,這個方        法執行的時候,我們的 Activity 已經可見了,隻是我們還看不到。

              onRestart:

              這個方法是我們重新啟動的時候會回調的,當我們的 Activity 從可見到不可見,再由不可見變為可見,這個          方法就會調用,這個方法和使用者的操作息息相關,比如使用者點了 home 再次回到 APP,或者使用者從 A 界面到 B          界面,然後點選了傳回鍵都會回調這個方法。

              onResume:

              這個方法和 onStart 的差別就是當這個方法回調的時候,Activity 已經出現在前台了,onStart 回調的時候               Activity 還在背景,是以當回調這個方法的時候,Activity 已經可見了。

              onPause:

             這個方法表示 Activity 正在停止,正常情況下,這個方法執行之後就會執行 onStop 方法,不過在極端情況             下,當使用者迅速點選傳回鍵的時候,會直接執行 onResume 方法。因為隻有這個方法執行完成,新的 Activity 的         onResume 方法才會執行,是以不要在這個方法中執行一些耗時的操作,因為如果執行耗時操作的話,跳轉會慢         很多。

              onStop:

              這個方法執行的時候表示 Activity 即将停止,可以做一些相對耗時的操作,同樣不能太耗時。注意:如果                Activity 使用了透明主題,那麼不會回調這個 onStop 方法。

              onDestory:

              此方法執行之後表示 Activity 正式被銷毀,那在這個方法中我們一定要執行資源回收和釋放,不然很容易引           起記憶體洩漏。

        最後提出一個問題 onStart 和 onResume ,onPause 和 onStop 有什麼不同?

        答:對于我們使用,那麼最主要的差別就是 onStart 和 onStop 主要是區分 Activity 是否可見來回調的,那                          onPause 和 onResume 主要是區分 Activity 是否位于前台來區分的。

       2.2 異常情況下的聲明周期

             首先說一下, 我們的 Activity 的三種運作狀态:

             ①、前台 Activity ,也就是正在和使用者進行互動的 Activity。

②、可見但是非前台的 Activity,也就是說這個 Activity 彈出了一個 dialog 導緻 Activity 可見但是位于背景

無法互動

③、背景 Activity,已經被暫停的 Activity,比如執行了 onStop。

這三種 Activity 最有可能被回收記憶體的就是第三種,那麼被回收的 Activity 重新打開的生命周期和我們正常 打開的生命周期肯定是不一樣的,那麼我們下面就說一下異常情況下的 Activity 的生命周期中增加了哪些。 說到記憶體重新開機,我們不得不說一下我們在注冊 Activity 的時候指定的 configChange 屬性,指定這個屬性的時候 我們可以指定哪些地方不用重新開機 Activity ,例如可以指定 : locale(裝置本地位置改變,一般指切換了語言) orientation (螢幕的旋轉) keyboardHidden(鍵盤的可通路發生了改變) 如果指定多個可以用 | 進行隔開。

好了下面說一下異常情況的生命周期: onSaveInstanceState:這個方法一般執行在 onStop 之前,不一定執行在 onPause 之前或者之後,一定 要記住,這個方法隻有在異常的時候才會回調的。 onRestoreInstanceState:這個方法一般是我們恢複資料的時候要去實作的,在 onStart 方法之後執行, 這個方法中有一個 Bundle 恢複資料的時候也是根據這個 Bundle 去恢複的。其實在恢複資料的時候大部分 的資料系統都是幫我們恢複好的,比如 Listview 的位置,還有 View 填寫的資訊等,如果想知道到底恢複了 哪些資料,可以看一下每個 View 的源碼,每個 View 中都有 Save 和 Restore 方法的。 最後說一下異常時候儲存資料的流程,首先是 Activity 的 onSaveIntanceState 去儲存資料,然 Activity委托 window 去儲存資料,最後,window 再去委托 DecorView 去儲存資料,最後 DecorView 在去通知每個 View 儲存資料,這樣就完成了儲存資料的整個流程。

三、啟動模式

       啟動模式的指定可以改寫我們 Activity 棧的順序,進而修改我們傳回的 Activity,我認為最大的作用就是我們的返        回退出。啟動模式可以通過 lunchMode 指定。 好了不說這些,下面說正題,Activity 的四種啟動模式。

       ①、standard

        定義我就不再這裡說明了,這裡說一個我們在使用中遇到的問題,在我們用 Application 的 context 去進行跳轉           的時候,我們會跳轉失敗,因為我們新啟動的 Activity 需要一個 task,而 context 沒有 task,這樣就會出現問             題,解決辦法就是我們跳轉的時候給 Activity 指定一個 task。

        當我們啟動一個 Activity 的時候指定了一個 task ,那麼系統會先建立 task 再去建立 Activity 。

       ②、singleTop

        這個啟動模式知識點也就一個,那就是當我們啟動的 Activity 在棧頂的時候,這個 Activity 會調用 onNewIntent           方法。

       ③、singleTask

        singleTask 和 singleTop 最大的差別就是會執行 clearTop 操作。clearTop 操作會将目标 Activity 上面的全

部 Activity 出棧。

       ④、singleIntance

        它是 singleTask 的加強版,當我們啟動一個新的 Activity 回去重新建立一個 Task,這樣我們的 Activity 就運作在

        一個獨立的 Task 中。

        下面說幾種特殊情況:

1、當 B 啟動模式為 singleInstance 的時候, A -> B B為一個 task, B->C 那麼 C 的 task 和 A的 task 是相 同的。 也就是說 C 被壓在 A 的上面了。但是如果從外部程式啟動 B ,B 在啟動 C 那麼 other -> B -> C 這三個的 taskid 是都不相同的

2、AB在前台任務棧,CD在背景任務棧,CD啟動得 lunchMode 為 singleTask,這時我們通路 D,這個時候會把 CD 放到前台任務棧,是以現在前台任務棧為 ABCD 。

        上文中我們多次提到了 Task,那麼這個 Task 到底是什麼呢,下面看看我的了解:

Task: 這個 task 是辨別 Activity 存儲在哪裡的,每個 Activity 都會有一個 task 存儲,每個 Activity 的 task 名 字都是應用的包名,是以當我們想指定 task 的時候不能指定和包名一樣。這個 task 分為前台 task 和背景 task,背景 task 都是存儲暫停的 Activity。 allowTaskPeparenting :當我們給某個 Activity 的這個屬性設定為 true 的時候,當我們從應用 A 啟動應用 B 的 Activity 的時候,并且這個 Activity 設定了 allowTaskPeparenting = true,那麼 B 的 Activity 的 Task 會從 A 的 task 轉到了 B 的task。也就是說我們隻要啟動了 B 的任何一個 Activity ,那麼 B 的 Task 就會建立出來。 在 AndroidManiFest 中可以通過指定 taskAffinity 屬性來指定 Activity 的 task,不過包名中間必須有分隔符。

四、使用中注意的問題

       1、當我們每次新啟動一個 Activity 的時候,我們的舊 Activity 的 onPause 方法總會最先調用,是以在我們跳                    轉的時候不要在 onPause 方法中執行耗時的代碼,這樣會導緻跳轉緩慢。

       2、有兩種方法可以指定 lunchMode 一種是配置,一種是在 Intent 中設定,後者的優先級高于前者。

總結:

       這些都是在項目中總結出來的一些經驗,如果有什麼出入歡迎指出,我們共同進步。謝謝。

       雅歌不會編代碼

       2017/07/10