一般情況下,Android程序的流程都運行在activity中,activity具有自己的生命周期,由系統來控制。可以使用onSaveInstanceState()和onRestoreInstanceState()方法來保存和恢復狀態。activity之間通過Intent來進行跳轉和數據傳輸。
Activity的生命周期如圖所示:
由上圖可知Activity生命周期有三個關鍵的循環:
1、整個的生命周期,從onCreate(Bundle)開始到onDestroy()結束。
Activity在onCreate()設置所有的“全局”狀態,在onDestory()釋放所有的資源。例如:某個Activity有一個在后台運行的線程,用於從網絡下載數據,則該Activity可以在onCreate()中創建線程,在onDestory()中停止線程。
2、可見的生命周期,從onStart()開始到onStop()結束。
在這段時間,可以看到Activity在屏幕上,盡管有可能不在前台,不能和用戶交互。在這兩個接口之間,需要保持顯示給用戶的UI數據和資源等,例如:可以在onStart()中注冊一個IntentReceiver來監聽數據變化導致UI的變動,當不再需要顯示時候,可以在onStop()中注銷它。onStart(),onStop()都可以被多次調用,因為Activity隨時可以在可見和隱藏之間轉換。
3、前台的生命周期,從onResume()開始到onPause()結束。
在這段時間里,該Activity處於所有 Activity的最前面,和用戶進行交互。Activity可以經常性地在resumed和paused狀態之間切換,例如:當設備准備休眠時,當一個 Activity處理結果被分發時,當一個新的Intent被分發時。所以在這些接口方法中的代碼應該屬於非常輕量級的。
常見的生命周期過程:
1、啟動Activity:系統會先調用onCreate方法,然后調用onStart方法,最后調用onResume,Activity進入運行狀態。
2、當前Activity被其他Activity覆蓋其上或被鎖屏:系統會調用onPause方法,暫停當前Activity的執行。
3、當前Activity由被覆蓋狀態回到前台或解鎖屏:系統會調用onResume方法,再次進入運行狀態。
4、當前Activity轉到新的Activity界面或按Home鍵回到主屏,自身退居后台:系統會先調用onPause方法,然后調用onStop方法,進入停滯狀態。
5、用戶后退回到此Activity:系統會先調用onRestart方法,然后調用onStart方法,最后調用onResume方法,再次進入運行狀態。
6、當前Activity處於被覆蓋狀態或者后台不可見狀態,即第2步和第4步,系統內存不足,殺死當前Activity,而后用戶退回當前Activity:再次調用onCreate()、onStart()、onResume(),進入運行狀態。
7、用戶退出當前Activity:系統先調用onPause(),然后調用onStop(),最后調用onDestory(),結束當前Activity。
Activity生命周期中涉及到的函數如下:
protected void onCreate(Bundle savedInstanceState):Activity被創建時調用
protected void onStart():Activity被創建或者從后台回到前台時調用
protected void onRestart():Activity從后台回到前台時調用
protected void onResume():Activity創建或者或者從被覆蓋、后台重新回到前台時調用
protected void onPause():Activity被覆蓋或者鎖屏時被調用
protected void onStop():Activity跳轉到新的Activity或者退出時調用
protected void onDestroy():Activity退出時調用
Activity用來保存和恢復狀態的方法如下:
protected void onSaveInstanceState(Bundle outState)
Activity被系統殺死時調用,如屏幕橫豎屏切換Activity被銷毀再重建等。
(1)在Activity被覆蓋或退居后台之后,系統資源不足將其殺死,此方法會被調用;
(2)在用戶改變屏幕方向時,此方法會被調用;
(3)在當前Activity跳轉到其他Activity或者按Home鍵回到主屏,自身退居后台時,此方法會被調用。
第一種情況我們無法保證什么時候發生,系統根據資源緊張程度去調度;第二種是屏幕翻轉方向時,系統先銷毀當前的Activity,然后再重建一個新的,調用此方法時,我們可以保存一些臨時數據;第三種情況系統調用此方法是為了保存當前窗口各個View組件的狀態。onSaveInstanceState的調用順序是在onPause之前。
protected void onRestoreInstanceState(Bundle savedInstanceState)
Activity被系統殺死后重新創建時調用,如屏幕橫豎屏切換Activity被銷毀再重建等。
(1)在Activity被覆蓋或退居后台之后,系統資源不足將其殺死,然后用戶又回到了此Activity,此方法會被調用;
(2)在用戶改變屏幕方向時,重建的過程中,此方法會被調用。
我們可以重寫此方法,以便可以恢復一些臨時數據。onRestoreInstanceState的調用順序是在onStart之后。
public void onWindowFocusChanged(boolean hasFocus)
Activity窗口獲得或失去焦點時被調用,例如創建時首次呈現在用戶面前;當前Activity被其他Activity覆蓋;當前Activity轉到其他Activity或按Home鍵回到主屏,自身退居后台;用戶退出當前Activity。
透明主題從一個activity A跳轉到另外一個activity B:
A:onPause()
注意不會調用onStop()方法,因此activity B finish()之后activity A不會調用onRestart()方法。
從activity B返回activity A
A:onResume()
設置activity主題透明:
示例代碼如下
<style name="AppTheme" parent="AppBaseTheme">
<item name="android:windowIsTranslucent">true</item>
</style>
<style name="ThemeActivity" parent="@android:style/Theme.Light.NoTitleBar">
<item name="android:windowIsTranslucent">true</item>
</style>
<style name="WXTheme" parent="AppBaseTheme">
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowBackground">@android:color/transparent</item>
</style>
解決方法:
activity跳轉返回修改狀態可使用onActivityResult()方法。
Activity全屏設置
方式1:AndroidManifest.xml
<activity android:name="MainActivity" android:theme="@android:style/Theme.NoTitleBar.Fullscreen" />
方式2:代碼實現
requestWindowFeature(Window.FEATURE_NO_TITLE); // 隱藏標題欄
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN); // 隱藏狀態欄
注意:設置全屏的代碼必須在setContentView(R.layout.main) 之前,不然會報錯。
Activity橫豎屏設置
方式1:AndroidManifest.xml
<activity android:name="MainActivity" android:screenOrientation="landscape" /> // 或者 “portrait”
方式2:代碼實現
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
獲取橫屏方向
int orientation = this.getResources().getConfiguration().orientation;
orientation 的常用取值可以為 ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE(橫屏) 或 ActivityInfo.SCREEN_ORIENTATION_PORTRAIT(豎屏)
Activity屏幕一直顯示
1、AndroidManifest.xml添加權限
<uses-permission android:name="android.permission.WAKE_LOCK" />
2、代碼實現
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
Activity啟動過程
可將其分為6個過程
1、使用代理模式啟動到ActivityManagerService中執行。
2、創建ActivityRecord到mHistory記錄中。
3、通過socket通信到Zygote相關類創建process。
4、通過ApplicaitonThread與ActivityManagerService建立通信。
5、ActivityManagerService通知ActivityThread啟動Activity的創建。
6、ActivityThread創建Activity加入到mActivities中並開始調度Activity執行。
Activity主要包括以下屬性:
taskAffinity
launchMode,啟動模式
allowTaskReparenting
clearTaskOnLaunch
alwaysRetainTaskState
finishOnTaskLaunch
taskAffinity屬性
默認情況下,一個應用程序中的所有activity都有一個affinity,它們屬於同一個Task。
每個activity可以通過<activity>中的taskAffinity屬性設置單獨的affinity。
1、不同應用程序中的activity可以共享同一個affinity。
2、同一個應用程序中的不同activity也可以設置成不同的affinity。
affinity屬性在2種情況下起作用:
1、啟動activity的Intent對象包含FLAG_ACTIVITY_NEW_TASK標記。
2、啟動activity的allowTaskReparenting被設置成true。
主要的Intent標記如下:
FLAG_ACTIVITY_NEW_TASK:如果啟動activity的affinity屬性與當前所有的task的affinity屬性都不相同,系統會新建啟動activity的affinity屬性
的Task,並將啟動activity壓入新建的Task棧中,否則將啟動activity壓入affinity屬性相同的Task中。
FLAG_ACTIVITY_CLEAR_TOP:
FLAG_ACTIVITY_RESET_TASK_IF_NEEDED:
FLAG_ACTIVITY_SINGLE_TOP:
Activity啟動模式launchMode屬性有四種值:
standard、singleTop、singleTask和singleInstance。
standard:默認模式,可省略。在這種啟動模式下,都會默認創建一個新的實例。因此,這種模式允許多個重復Activity疊加。
singleTop:這種模式允許有多個實例,但不允許多個重復Activity疊加。如果Activity位於棧頂,不會創建新的實例,而會調用onNewIntent()方法。
singleTask:這種模式只有一個實例。在同一應用程序中啟動時,若Activity不存在則在當前Task創建一個新的實例,若Activity存在則將Task中在其之上的其它Activity銷毀,並調用此Activity的onNewIntent()方法。
singleInstance:這種模式只有一個實例,並且該實例獨立運行在一個Task中。這個Task只有該實例,不允許其它Activity存在。
allowTaskReparenting屬性
該屬性設置為true,則啟動activity可以從一個Task移動另一個相同affinity的Task中。
clearTaskOnLaunch屬性
如果棧底activity的這個屬性被設置為true,一旦用戶離開task,則task棧中的activity將被清空到只剩下棧底activity。這種情況與alwaysRetainTaskState相反。即使用戶只是短暫地離開,task也會返回到初始狀態,即只剩下棧底acitivty。
alwaysRetainTaskState屬性
如果棧底activity的這個屬性被設置為true,則Task中的所有activity將被長時間保存。
finishOnTaskLaunch屬性
這個屬性與clearTaskOnLaunch相似,但它只對單獨的activity操作,而不是整個task。它可以結束任何activity,包括棧底的activity。當它設置為true時,當前的activity只在當前會話期間作為task的一部分存在,當用戶退出activity再返回時,它將不存在。