標籤:
當使用者在用一個App的時候,Activity會在生命週期不同的狀態下轉換。
當使用者離開或重新回到一個Activity,我們可以在生命週期的回呼函數中來寫一些相關的操作。比如,如果使用者開啟了一個視頻播放器,當他直接切換到另外一個App,這時候應該使播放器暫停,斷開擷取視頻資源的網路連接。當使用者回來,我們要重新串連網路擷取視頻資源,讓使用者在剛才暫停位置開始重新觀看。
接下來,開始去瞭解非常重要的生命週期的回呼函數,學著怎麼去用它們來執行一些使使用者有更好體驗的操作,並且當我們不需要它們時,不要消耗系統的資源。在Android系統中,不是跟其他程式一樣會啟動一個main()方法, 而是通過調用對應生命週期特定狀態的回呼函數,來開始一個Activity執行個體.
啟動一個Activity
在一個Activity的生命週期中,其中的回呼函數可以看成一個階梯金字塔。也就是,每一個Activity生命週期的階段就是金字塔上的一個台階。當系統開始啟動一個Activity時,其中的回呼函數會讓Activity一個台階一個台階地登上最高的那一台階。在最高的那一層台階,運行時Activity可以完全顯示出來,和使用者進行互動。
當使用者退出當前的Activity,系統會調用其它的方法,讓Activity從最高那層台階往下走,它就不會在前台了。有些時候,它只是從金字塔往下走了一部分,然後在那等著(比如說使用者切換到其它的App)。這個時候這個Activity還是可以往上走回到金字塔最高那一層(使用者又回到了之前的Activity),使用者繼續在剛才離開的地方進行操作。
可能實際開發上不需要實現所有的生命週期函數,但是瞭解每一個函數的實現,確保App執行的是使用者期望的方式,這是非常重要的。
以下是要注意的幾個方面:
1、當使用者有來電或者切換到其它的App,不要銷毀當前的App
2、當使用者沒有用到系統的資源,要關掉,不要消耗系統資源
3、當使用者離開App一會後再到App,不要丟失使用者的進度
4、當螢幕在橫向和縱向之間旋轉時,不要失去使用者的進度。
Activity在不同的階段轉換時,如。
但是,只有三個階段是靜態。Activity只會在這三個階段其中一個階段上長時間停留:
Resumed
在這一階段,Activity會顯示在前台上,和使用者進行互動。也就是啟動並執行階段。
Paused
在這個階段,Activity會被其他的Activity部分地遮蓋住,這時候的Activity不能接收使用者的輸入也不能執行任何代碼。
Stopped
當Activity在Stopped階段,會完全被掩蓋住,使用者不可見。這是的Activity執行個體和他的一些成員變數仍然保留,但它不會執行任何代碼了。
而在其他的階段 (Created 和 Started) 都是一瞬間的, 系統會調用下一個生命週期的函數,很快地跳到下一個階段。所以在系統調用 onCreate()之後,它很快就會調用onStart()接著馬上跟著 onResume()。
指定App的啟動Activity
在AndroidManifest.xml中,可以指定哪一個Activity用作main Activity。這個main Activity要在< intent-filter >中聲明,包含MAIN action 和 LAUNCHER category.
例如:
<activity android:name=".MainActivity" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter></activity>
OnCreate
大部分的App都會有幾個不同的Activity,當使用者點擊開啟App時,系統會通過調用onCreate()方法來建立每個新的Activity。
必須要實現 onCreate()方法來執行一些活動的UI、資料等載入,這在整個生命週期只執行一次。例如在XML中定義使用者介面口,定義成員變數,配置一些UI。
上一次DisplayActivity中的代碼:
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_display_message); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG) .setAction("Action", null).show(); } }); getSupportActionBar().setDisplayHomeAsUpEnabled(true); Intent intent = getIntent(); String message = intent.getStringExtra(MainActivity.EXTRA_MESSAGE); TextView textView = new TextView(this); textView.setTextSize(40); textView.setText(message); RelativeLayout layout = (RelativeLayout) findViewById(R.id.content); layout.addView(textView); }
一旦 onCreate()執行完成, 系統就會緊接著調用 onStart() 和 onResume() 方法. Activity不會停留在Created和Started這兩個階段。其實,當onStart()方法被調用的時候,使用者已經可以看見Activity,只不過onResume()會馬上被調用,Activity就進入在Resumed這一狀態,直到使用者切換到另一個App或者有來電了,又或者關閉了螢幕。
當建立一個新的Activity執行個體時,重點關注這三個回調方法 :onCreate(), onStart(), 和 onResume()。一旦回調方法執行完成,Activity就會到Resumed這一階段,即Activity回到前台,使用者就可以和這個Activity進行互動。
onDestroy
onCreate()在生命週期中是第一個執行的方法,而onDestroy()是生命週期中最後一個執行的方法. 系統在Activity中調用onDestroy()這個方法作為結束的訊號,Activity執行個體會從系統記憶體中移除。
大部分App都不需要實現這個方法,因為Activity調用onDestroy()前,應該在onPause() 和onStop()這兩個方法中執行清除記憶體操作。但是如果Activity中有線程是在onCreate()中或者一些長期啟動並執行資源,如果不合適地關掉的話,會造成記憶體流失!這是時候應該在最後的onDestroy()方法中關掉它們。
@Overridepublic void onDestroy() { super.onDestroy(); }
系統在調用onPause()和onStop()方法之後,就會調用onDestroy()用。
除了一種情況:就是在onCreate()中調用finish()方法。
有時候,比如Activity執行一個臨時的決策來啟動另一Activity,就會在onCreate()中調用finish()方法。這種情況,系統會馬上調用onDestroy()方法,不會再經過生命週期的其他回調方法。
OnPause()和onResume()
在使用者使用app時,前台Activity有時被其他組件遮住,會導致Activity暫停。例如,當一個提示對話方塊開啟,Activity就會暫停。雖然仍可以看見部分的Activity,但是Activity已經暫停,不會執行任何操作。如果Activity一旦完全被遮蓋著看不見,它就停止了。會進入Stopped這一狀態。
當Activity進入Paused狀態,系統會在Activity中調用onPause(),比如會暫停視頻,或者暫時儲存 一些資訊。當使用者從Paused狀態返回到當前的Activity,系統就會調用onResume()方法,重新回到Resumed狀態。
當系統調用onPause(),Activity部分可見。但大多數的情況是,使用者會離開當前的Activity,就會進入Stopped狀態,最後執行onDestroy()方法。所以呢,在onPause()中會做一下幾點:
1、停止會消耗CPU的動畫或者正在啟動並執行操作。
2、提交未儲存的修改,比如草稿郵件/3、釋放系統資源,比如廣播接收器,GPS,或者當Activity暫停,而使用者又不需要用到的資源
例如,App用到相機,那麼onPause()方法是一個非常合適的地方來釋放它
@Overridepublic void onPause() { super.onPause(); //首先調用父類的方法 // 釋放資源,因為其他的Activity可能需要用到它 if (mCamera != null) { mCamera.release(); mCamera = null; }}
注意,不要在onPause()方法中執行資料庫的操作,因為這會使跳轉到下一個Activity很緩慢。
在onPause()執行一些相對簡單的操作,以致於可以快速地跳轉到下一個Activity。當Activity停止,這時候Activity執行個體會放在記憶體中,當Activity恢複時,就會重新調用這個執行個體,不需要再重新建立一個Activity執行個體。
需要知道的是,每一次系統調用onResume()方法,Activity就會回到前台,其中也包括了第一次建立執行個體的時候。
應該在onResume()方法中初始化一些在onPause()被釋放掉的組件,還有每次恢複所需要的組件,比如一些開始的動畫和需要的組件。
以下onResume()對應上面onPause()的例子,初始化在Pasued狀態被釋放掉的相機。
@Overridepublic void onResume() { super.onResume(); if (mCamera == null) { initializeCamera(); // 初始化相機的操作 }}
Android成長之路(3)——Activity的生命週期(1)