恰當的停止和重新啓動你的activity,在activity的生命週期裏面這個是非常重要的,這種機制可以讓用戶的覺得你的APP一直是在運行的,即使他不在你的程序的activity界面,但是並不會丟失這個程序的運行進度.下面是幾個重要的使用場景:
- 當用戶打開最近使用的APP程序列表(長按HOME按鍵),這個時候用戶選擇一個APP,那麼用戶就由你的APP轉移進入到另外一個APP裏面,你的APP將不再前臺運行,而當用戶再次打開最近使用的程序列表,選擇打開你的APP的時候,這個時候你的APP又重新啓動了。
- 當用戶在你的應用上進行一個操作,啓動了另外一個新的Activity(一個APP裏面是可以有多個activity的,每個activity都是一個展示界面,展現不同視圖),這個時候你當前的activity就進入了stopped狀態,當點擊返回鍵的時候,這個activity又重新啓動。
- 當用戶使用你的app的時候,接到一個電話,通話結束後,你的app又重新回到前臺
Activity
類提供了這兩個生命週期函數:onStop()
和onRestart(),
分別的
對應activity暫停和重新啓動的時候的動作,
我們可以在這個2個函數來處理我們在activity暫停和重新啓動的時候要做的工作。是完全不可見的,完不像Stopped狀態,是部分遮蓋,可以的,Stopped狀態的時候,處於這個狀態的Acitvity全被覆蓋用戶的焦點完全在另外一個獨立的activity上或者是一個獨立的APP上。
注意:因爲當我們的activity進入到stopped狀態的時候,我們這個activity的實例還是存儲在系統的內存中。那這樣的話,也就允許我們不用自己去實現onStop()和onRestart()(甚至onStart()函數)。對於大多數的activity來說,都是相對簡單的,activity從停止到重新啓動都沒什麼問題,我們要做的也許僅僅是調用onPause來停止那些消耗資源的動作。
圖1:
如圖1所示,當用戶離開你的activity的時候,系統會調用它的onStop函數來停止這個activity,如果用戶返回到處於stopped狀態的activity的時候,系統會調用onRestart()函數,然後僅接着就調用onStart和onResume函數。不管是什麼情況下使得activity進入stopped狀態,系統肯定會在onStop函數之前先調用onPause()函數。
停止的Activity
當你的activity的onStop函數被調用的時候,意味着你的activity將要處於不可見的狀態,當用戶不使用它的時候,這個時候應該釋放絕大部分的資源。一但你的activity進入暫停狀態,那麼,系統可能因爲需要回收內存資源而銷燬你的activity實例。在極端情況下,系統可能直接殺死你的APP的進程,並且不回去調用你的activity的onDestroy回調函數。所以要在onStop中釋放那些可能會引起內存泄露的資源
儘管onPause函數會在onStop之前調用,但是你應該使用onStop函數來執行那些耗時,耗CPU功耗的操作,比方說往數據庫寫數據。
比方說下面的例子,就是實現了onStop來保存未完成的筆記到存儲器。
@Override
protected void onStop() {
super.onStop(); // Always call the superclass method first
// Save the note's current draft, because the activity is stopping
// and we want to be sure the current note progress isn't lost.
ContentValues values = new ContentValues();
values.put(NotePad.Notes.COLUMN_NAME_NOTE, getCurrentNoteText());
values.put(NotePad.Notes.COLUMN_NAME_TITLE, getCurrentNoteTitle());
getContentResolver().update(
mUri, // The URI for the note to update.
values, // The map of column names and new values to apply to them.
null, // No SELECT criteria are used.
null // No WHERE columns are used.
);
}
當activity暫停的時候,運行在後臺,這個activity的實例會被保存在內存裏, 當我們重新恢復到前臺的時候,系統會調用這個被保存的實例。你不需要再去重新初始化那些在生命週期的Resumed狀態之前的被初始化的數據。而且系統會保存佈局文件裏面每個View的狀態。所以如果用戶在EditText裏面輸入了一些內容,那麼在stopped的時候,它的內容會被自動保存的,我們不需要去存儲它。
注意:即使當系統銷燬了除了stopped狀態的activity,但是這個activity裏面的view對象的狀態還是會被保存下來(比方說一個EditText裏面的文字內容),這個信息會被保存到Bundle(鍵值對的一個容器)裏面,當用戶再次進入這個activity的重新創建的一個實例的時候,可以恢復原來裏面的view對象的狀態,下一節我們會講如何利用Bundle來保存其他的一些數據的狀態,來防止你的你的activity實例被銷燬,重建時候,造成數據損失。
啓動/重新啓動你的Activity
當你的activity從stopped狀態轉到前臺運行,系統會調用它的onRestart函數。系統同樣調用onStart函數,每次你的activity變爲可見的時候,都會調用它(不管你是restart,或者是第一次create這個activity).onRestart函數只有在activity從stopped狀態恢復到前臺運行的時候,纔會調用。所以當activity從stopped狀態恢復,而未被destoryed的情況下,你可以在它裏面實現一些特別的恢復工作。
通常讓APP利用onRestart來恢復activity之前的狀態這種情況是很罕見的,我們幾乎不這麼使用它,所以在一些普通的app上對這個方法的使用沒有任何指導的方法。因爲你onStop函數應該清理你的activity的資源,在restart你的activity的時候,你需要重新去實例化這些資源。當你的activity應用第一次啓動的時候也需要去實例化它們。因爲這個原因,所以很多時候我們使用onStart函數來和onStop函數對應,因爲不管你是第一次創建,還是從stopped狀態restart你的activity,系統都會調用onStart這個函數,而onRestart僅僅在stopped狀態恢復的時候纔會調用。。
比方說用戶長時間離開activity界面,那麼當回到這個界面的時候,onStart函數是一個很好的地方來識別那些需要的系統特性是可以使用的。
@Override
protected void onStart() {
super.onStart(); // Always call the superclass method first
// The activity is either being restarted or started for the first time
// so this is where we should make sure that GPS is enabled
LocationManager locationManager =
(LocationManager) getSystemService(Context.LOCATION_SERVICE);
boolean gpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
if (!gpsEnabled) {
// Create a dialog here that requests the user to enable GPS, and use an intent
// with the android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS action
// to take the user to the Settings screen to enable GPS when they click "OK"
}
}
@Override
protected void onRestart() {
super.onRestart(); // Always call the superclass method first
// Activity being restarted from stopped state
}
當系統銷燬你的activity的時候,會調用 onDestroy()
這個函數。因爲我們大部分的釋放系統資源的工作都是在onStop裏面進行的,所以在onDestroy裏面就不需要做很多事情。onDestroy是你最後的機會來清理那些可能會引起內存的泄露的資源,所以你要確保那些額外的線程都被銷燬,其他一些長時間運行的工作也被終止。