【Android】Android四大組件之Activity(二)
【Android】Android四大組件之Activity(二)
前言
在這篇文章之前,我已經寫過了一篇有關Activity的內容,是關於activity之間的頁面跳轉和數據傳遞,而這篇文章著重強調的是Activity中的有關生命周期的理解。
1、什麼是生命周期?
在之前學習Java的時候,Java中的一個類的對象就涉及到了生命周期,包括它的生成、作用、回收等等。
在Android中也有差不多的生命周期的概念,是針對Activity
的。
首先,給出Android開發文檔中對生命周期的介紹:了解 Activity 生命周期
在官方文檔的基礎上,我們來理解各個生命周期!
當用戶瀏覽、退出和返回到您的應用時,應用中的 Activity
實例會在其生命周期的不同狀態間轉換,而為了在 Activity 生命周期的各個階段之間導航轉換,Activity 類提供六個核心回調:onCreate()
、onStart()
、onResume()
、onPause()
、onStop()
和 onDestroy()
。當 Activity 進入新狀態時,系統會調用其中每個回調。
以下是官方文檔對六大生命周期回調方法
的簡化視圖:
2、onCreate()
2.1 基本解析
因為生命周期是從上向下執行的,我們首先分析最開始的onCreate()
方法
onCreate()
,這個是activity被首次創建的時候調用的方法,而且我們必須在每個activity中重寫該方法!這個方法在activity生命周期中只出現一次,如果第二次出現,那麼說明上一個activity已經調用了onDestroy()方法,被銷毀了。
相信你對下面的程式碼不陌生,因為每個activity中都會有這樣類似作用的程式碼!
private TextView photo;
private ImageView pic;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera);
photo = this.findViewById(R.id.tv_photograph);
pic = this.findViewById(R.id.iv_pic);
photo.setOnClickListener(this);
}
在開始構建activity的時候,我們在onCreate()
方法中我們都會會將數據綁定
到列表,將 Activity與各個組件相關聯,並實例化
某些類作用域變數。
我們在上述的程式碼例子中可以發現,我們實例化了photo這個TextView
還有pic這個ImageView
,並且在此之前,我們一定會給當前這個activity綁定一個xml布局文件,通過調用setContentView()
方法,然後通過R.layout
找到我們需要的布局xml進行綁定。
2.2 你可能疑惑的savedInstanceState
以下內容感興趣的可以看看,初學者如果不明白其實也不需要太懂。
細心的你會發現,onCreate()其實傳入了一個Bundle
類的對象參數savedInstanceState
,這是個啥玩意?
接下來,我們對savedInstanceState進行詳細解釋!
首先我們分析以下Bundle
類是啥,說通俗一點,就是實現了Parcelable
介面的一個鍵值對
官方的簡介是:
A mapping from String keys to various
Parcelable
values.
也就是說,這個類實例化的對象是可以存儲數據
的,並且是以鍵值對
的形式存儲的,實現了Parcelable
介面
而傳入的savedInstanceState
對象,字面翻譯就是保存過的實例狀態
,並且我們上面說了,savedInstanceState
都對象可以存儲鍵值對,也就是說有兩種情況:
savedInstanceState
不為nullsavedInstanceState
是null的
事實上,savedInstanceState
為null的情況是最常見的,但是什麼情況savedInstanceState
不為空呢?
2.2.1 onSaveInstanceState()方法
根據文檔,我們發現,Activity類中有一個onSaveInstanceState()
方法,不同於onCreate()
這種生命周期方法,onSaveInstanceState()
只有在進入某種「activity有被殺死的風險」的狀態下,才會被調用
會執行onSaveInstanceState()
方法的情況,官方文檔中是如下解釋的:
Android calls onSaveInstanceState() before the activitybecomes vulnerable to being destroyed by the system, but does not bothercalling it when the instance is actually being destroyed by a user action (suchas pressing the BACK key).
當某個activity變得”容易”被系統銷毀時,該activity的onSaveInstanceState()就會被執行,除非該activity是被用戶主動銷毀的,例如當用戶按BACK鍵的時候。
通俗一點,就是進入某種「activity有被殺死的風險」狀態,onSaveInstanceState()
方法就會被調用
也許你想到了很多的情況,我總結了一共如下的情況會調用onSaveInstanceState()
方法:
- 當用戶按下HOME鍵後。(這種情況,系統不知道你按下HOME後要運行多少其他的程式,自然也不知道activity A是否會被銷毀,因此系統會調用
onSaveInstanceState()
,讓用戶有機會保存某些非永久性的數據) - 調出程式管理,選擇運行其他的程式時。(同樣是可能記憶體不夠被系統kill掉)
- 按下息屏鍵關閉螢幕時(一樣的道理,手機廠家會設置息屏後進程的狀態,也可能被kill)
- 從activity A中啟動一個新的activity B時。(例如從QQ打開某tx遊戲,遊戲的資源調用很大,可能把QQ的進程kill掉,雖然大多數情況我們是給QQ後台許可權的)
- 螢幕方向切換時,例如從豎屏切換到橫屏時。(在螢幕切換時,系統會銷毀activity A,在螢幕切換之後系統又會自動地創建activity A,所以
onSaveInstanceState()
一定會被執行,且也一定會執行onRestoreInstanceState()
)
說專業一點:只要某個Activity是做入棧並且非棧頂
時(啟動跳轉其他Activity或者點擊Home按鈕),此Activity是需要調用onSaveInstanceState()
的, 如果Activity是做出棧
的動作(點擊back或者執行finish),是不會調用onSaveInstanceState
的。
2.2.2 onRestoreInstanceState()方法
與onSaveInstanceState()
對應的是onRestoreInstanceState()
方法,但是——這兩個方法並不是成對出現,執行了“onSaveInstanceState()不一定執行
onRestoreInstanceState()`
onRestoreInstanceState()
執行的條件是:只有在Activity真的被系統非正常殺死過,恢復顯示Activity的時候,就會調用onRestoreInstanceState()
簡單來說,執行了onSaveInstanceState()存儲了數據狀態,並不一定會調用onRestoreInstanceState()來返回狀態,但是如果確實時非正常的kill進程,那麼會調用onRestoreInstanceState()返回onSaveInstanceState()存儲的數據
我們可以看看Android開發文檔中給出的例子:
TextView textView;
// some transient state for the activity instance
String gameState;
@Override
public void onCreate(Bundle savedInstanceState) {
// call the super class onCreate to complete the creation of activity like
// the view hierarchy
super.onCreate(savedInstanceState);
// recovering the instance state
if (savedInstanceState != null) {
gameState = savedInstanceState.getString(GAME_STATE_KEY);
}
// set the user interface layout for this activity
// the layout file is defined in the project res/layout/main_activity.xml file
setContentView(R.layout.main_activity);
// initialize member TextView so we can manipulate it later
textView = (TextView) findViewById(R.id.text_view);
}
// This callback is called only when there is a saved instance that is previously saved by using
// onSaveInstanceState(). We restore some state in onCreate(), while we can optionally restore
// other state here, possibly usable after onStart() has completed.
// The savedInstanceState Bundle is same as the one used in onCreate().
@Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
textView.setText(savedInstanceState.getString(TEXT_VIEW_KEY));
}
// invoked when the activity may be temporarily destroyed, save the instance state here
@Override
public void onSaveInstanceState(Bundle outState) {
outState.putString(GAME_STATE_KEY, gameState);
outState.putString(TEXT_VIEW_KEY, textView.getText());
// call superclass to save any view hierarchy
super.onSaveInstanceState(outState);
}
可以看到重寫的onSaveInstanceState()
方法中存入了遊戲狀態
和textView
的文字,在onRestoreInstanceState()
方法中,調用了獲取當前文字並設置
的方法,並且我們可以在這個例子中看到onCreate()
方法中是如何利用savedInstanceState
這個對象的——不為空那麼就獲取數據
if (savedInstanceState != null) {
gameState = savedInstanceState.getString(GAME_STATE_KEY);
}
3、onStart()
當 Activity 進入「onStart」狀態時,系統會調用onStart()
方法。onStart()
調用使 Activity 對用戶可見,也就是在這個方法中,我們可以看到app的前端activity展示了
onStart()
方法會非常快速地完成,並且與onCreate()一樣,Activity 不會一直處於「onStart」狀態。一旦此回調結束,Activity 便會進入「onResume」狀態,系統將調用 onResume()
方法。
4、onResume()
onResume
是應用與用戶互動的狀態,也就是具有焦點,我們可以對app中的各種組件進行操作的一個焦點狀態,這個時候是用戶與應用的交互的狀態。
5、onPause()
onPause
狀態是用戶對這個activity失去焦點
,但是onPause這個狀態,用戶還是對activity可見
的。
舉個例子,有兩個activity,第一個activity A,第二個activity B。
如果A使用透明主題
,B使用默認主題。當由A通過Intent跳轉到B時,會失去A的焦點,調用onPause()
方法,但是,因為時透明主題,所以我們在看B的同時,可以看到A,也就是A仍然是可見的,所以A不會調用onStop()
,也就是不會被停止
如果這個時候我們點擊back
按鈕,從B返回到了A,A會重新調用onResume()
方法,因為A得到了焦點
,但是並不會調用onStart()
,因為我們的A從來沒有被停止過
,仍然有可見的介面
6、onStop()
onStop
狀態就是我們對這個activity失去了焦點,但是它並未被銷毀
舉一個常見的例子——微信掃一掃
,我們從微信主頁打開微信掃一掃,主頁失去了焦點
並且不可見
,成為了onStop
的狀態,返回
之後主頁又得到了焦點
,執行了onStart()
和onResume()
7、onDestroy()
onDestroy
被執行,調用此回調的原因如下:
- Activity 即將結束(由於用戶
徹底關閉
Activity或由於系統為Activity調用finish()
方法 - 由於配置變更(例如
設備旋轉
或多窗口模式
),系統暫時銷毀Activit
如果Activity即將結束,onDestroy()
是 Activity 收到的最後一個生命周期回調。如果由於配置變更而調用 onDestroy(),系統會立即新建 Activity 實例,然後在新配置中為新實例調用onCreate()
8、橫豎屏的影響
在理解了各個部分的生命周期之後,我們應該注意到,在APP中橫豎屏的切換,會導致生命周期改變——先銷毀、再創建一個新的。
那麼我們可能遇到這樣的情況——我們豎屏看電影的時候,進度條在20分鐘,但是如果我們切換成了橫屏進度條就從頭開始了。這種APP出現的問題就是沒有處理橫豎屏切換帶來的影響。
之所以會出現上述情況,是因為activity的一個生命周期已經結束了,橫屏進入了一個新的生命周期。
解決方法有兩種:
- 在activity中設置
android:screenOrientation="landscape"
,這樣APP始終保持在橫屏。 - 在activity中設置
android:configChanges="keyboardHidden|screenSize|orientation"
,這樣activity在「鍵盤隱藏」、「螢幕大小變化」、「橫豎屏切換」的時候,不會產生影響。
一般遊戲開發使用第一種方法,因為遊戲需要一直橫屏。電影播放等使用第二種方法,這樣就可以保持橫豎屏進度條一致啦!
後話
關於Android中的activity中生命周期
的理解到此結束了,之後還有對activity的啟動模式
的分析!
建議搭配Android開發文檔進行觀看,文章內容僅供參考!