Android四大元件之Activity

koro發表於2020-09-21

Activity是啥?

簡單來說就是用來和使用者互動的介面,由各個控制元件組成 ,將內容介面化展現於使用者面前,接收使用者的觸控事件和使用者進行互動,可以說是使用最頻繁的元件了。

Activity生命週期

生命週期: onCreate -> onStart -> onResume ->onPause -> onStop-> onDestroy 以及 onRestart 方法

Activity生命週期圖

一個Activity從建立到銷燬的生命週期流程如下:

開啟一個介面

2019-01-26 15:36:04.134 30064-30064/com.sjc.myapplication I/生命週期-----MainActivity: onCreate: 
2019-01-26 15:36:04.207 30064-30064/com.sjc.myapplication I/生命週期-----MainActivity: onStart: 
2019-01-26 15:36:04.221 30064-30064/com.sjc.myapplication I/生命週期-----MainActivity: onResume: 
複製程式碼

按下返回鍵

2019-01-26 15:36:12.381 30064-30064/com.sjc.myapplication I/生命週期-----MainActivity: onPause: 
2019-01-26 15:36:12.943 30064-30064/com.sjc.myapplication I/生命週期-----MainActivity: onStop: 
2019-01-26 15:36:12.944 30064-30064/com.sjc.myapplication I/生命週期-----MainActivity: onDestroy: 
複製程式碼
  1. onCreate 介面被建立,我們一般在這裡進行一些檢視和資料以及響應事件的初始化工作。(initView(),initData(),initAction())
 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.layout_main);
        initView();
        initData();
        initAction();
    }
    private void initView(){};
    private void initData(){};
    private void initAction(){};
複製程式碼
  1. onStart 介面可見,此時介面還不可互動
  2. onResume 介面可以進行互動,比如觸發一些點選事件。
  3. onPause 介面失去互動,此時不可以進行互動。常見的導致該生命週期的執行的行為可能是:使用者按下Home鍵、按下back鍵、跳轉到下一個頁面、彈出一個Dialog,或者PopupWindow等。此時我們可以做一些儲存資料和停止動畫等,但是不能太耗時,否則會影響下個頁面的跳轉(頁面與頁面之前跳轉,先執行當前頁面的onPause方法,然後執行下一個頁面的 生命週期,具體執行下面有說明)。
  4. onStop 介面完全不可見的時候呼叫。兩個Activity跳轉,前一個Activity的onStop執行是在第二個Activity完全可見並可以進行互動後執行的(onCreate,onStart,onResume)
  5. onDestroy 介面被銷燬,一般我們在這裡做一些資源釋放的操作,比如登出廣播,關閉彈窗(如果頁面被銷燬,彈窗未被關閉,則會造成窗體洩漏),關閉動畫等。
  6. onRestart 介面重新可見,從一個頁面返回上一個頁面,首先會呼叫上一個頁面的 onRestart 方法,其次呼叫上一個頁面的 onStart、onResume方法
兩個頁面進行跳轉,ActivityA --> ActivityB 再從ActivityB按下返回鍵返回到ActivityA,其呼叫的生命週期方法為:
  • 首先啟動 ActivityA:
2019-02-18 23:08:28.362 4980-4980/com.sjc.myapplication I/生命週期-----ActivityA: onCreate: 
2019-02-18 23:08:28.388 4980-4980/com.sjc.myapplication I/生命週期-----ActivityA: onStart: 
2019-02-18 23:08:28.390 4980-4980/com.sjc.myapplication I/生命週期-----ActivityA: onResume: 
複製程式碼
  • 在 ActivityA 中啟動 ActivityB
2019-02-18 23:08:33.347 4980-4980/com.sjc.myapplication I/生命週期-----ActivityA: onPause: 
2019-02-18 23:08:33.371 4980-4980/com.sjc.myapplication I/生命週期-----ActivityB: onCreate: 
2019-02-18 23:08:33.393 4980-4980/com.sjc.myapplication I/生命週期-----ActivityB: onStart: 
2019-02-18 23:08:33.395 4980-4980/com.sjc.myapplication I/生命週期-----ActivityB: onResume: 
2019-02-18 23:08:33.819 4980-4980/com.sjc.myapplication I/生命週期-----ActivityA: onStop: 
複製程式碼
  • 在 ActivityB 中按下返回鍵
2019-02-18 23:10:59.457 4980-4980/com.sjc.myapplication I/生命週期-----ActivityB: onPause: 
2019-02-18 23:10:59.482 4980-4980/com.sjc.myapplication I/生命週期-----ActivityA: onRestart: 
2019-02-18 23:10:59.482 4980-4980/com.sjc.myapplication I/生命週期-----ActivityA: onStart: 
2019-02-18 23:10:59.483 4980-4980/com.sjc.myapplication I/生命週期-----ActivityA: onResume: 
2019-02-18 23:10:59.813 4980-4980/com.sjc.myapplication I/生命週期-----ActivityB: onStop: 
2019-02-18 23:10:59.814 4980-4980/com.sjc.myapplication I/生命週期-----ActivityB: onDestroy: 
複製程式碼

Activity銷燬時儲存資料

Activity 異常銷燬的時候,會呼叫 ==onSaveInstanceState== 方法儲存資料,該方法是在 onStop 之前執行,我們可以使用 Bundle 來儲存資料,當 Activity 重建的時候會呼叫 ==onRestoreInstanceState== 方法,我們可以通過 onRestoreInstanceState(Bundle savedInstanceState)傳遞過來的Bundle來獲取之前儲存的資料。進行資料恢復。當然也可以在onCreate(Bundle savedInstanceState)方法裡面取出來。

另:onSaveInstanceState 和 onRestoreInstanceState 方法中,系統自動為我們做了一些操作: 例如:Edittext 自動還原填寫內容, ListView 還原滾動位置,因為每一個View都有自己的 onSaveInstanceState 和 onRestoreInstanceState 方法。

activity異常銷燬的場景:

  • 1.螢幕旋轉會導致Activity重建(可以通過設定 android : configChanges = "orientation" 來防止Activity重建,還可以通過設定 android:screenOrientation="portrait" 鎖定Activity方向)
  • 2.記憶體吃緊,導致優先順序低的Activity被回收掉。

Activity 的四種狀態:

  1. running:處於前臺,和使用者進行直接的互動。(系統最不願意回收)
  2. Paused: 仍然可見,但是不可以互動。(系統不願意回收)
  3. Stoped: 不可見,處於後臺。(記憶體吃緊的時候,有可能會被回收)
  4. Killed: 被殺死,已經從Activity棧中移除。(系統傾向於回收這種 Activity)

Activity四種啟動模式:

通過在 mainfest 裡面的 android:launchMode= ""屬性來設定
複製程式碼
  • standard 標準模式,如果不設定啟動模式,Android 系統會預設將啟動模式設定為該屬性。每啟動一次 Activity 就會==建立一個例項==壓入棧中(連續啟動兩個一樣的 Activity ,會建立兩個例項,按照先後順序壓入棧中)。
  • singleTop 在建立例項的時候,首先會查詢任務棧==棧頂==是否有該 Activity 的例項存在,如果有就不再建立新的例項,直接使用棧中的例項。此時不會走 Activity 的 onCreate、onStart 生命週期方法,直接走 onPause--> onNewIntent --> onResume 方法。
  • singleTask 在建立例項的時候,首先查詢任務棧==棧中==是否有該例項的存在,如果有就不重新建立,直接將該例項的上面的所有例項(Activity)移除(Finish),也是不會走 Activity 的 onCreate、onStart 生命週期方法,直接走 onPause--> onNewIntent --> onResume 方法。
  • singleInstance 直接為該Activity在整個Android系統中建立一個==單獨的任務棧==(如果已經建立過,就不再重新建立),第一次建立時會走正常的生命週期流程,第二次直接走 onPause--> onNewIntent --> onResume 方法。

關於 taskAffinity 屬性(可以指定Activity所在的任務棧),在 launchMode 為 standard 和 singleTop 的時候是沒有作用的。具體作用體現在 singleTask 屬性上。 具體詳情連結 徹底弄懂Activity四大啟動模式

Activity任務棧:

  1. 棧是一個常用的資料結構,棧的特點是先進後出,佇列是先進先出
  2. Activity 是採用棧的資料結構進行管理的,最先開啟的 Activity 最後退出。
  3. 開啟一個應用的時候系統會預設分配一個任務棧,當所有 Activity 都退出時,棧就清空了。
  4. 在 Android 作業系統中是有多個任務棧的,一般一個應用對應一個任務棧。
  5. 預設情況下,關閉一個應用,就清空這個這個應用的任務棧,但是這個應用的程式還在。
參考文章:
  1. Android 四大元件
  2. 徹底弄懂Activity四大啟動模式

相關文章