——本文來自博客園Tekkaman的博客Android之Activity ,IBM的developerWorks網站張勇的詳解Android的Activity組件一文 ,CSDN博客hpoi的博客Android Activity的生命週期 ,感謝zzxap在CSDN論壇的自問自答——安卓工程運行是如何指定初始頁面的droid工程運行是如何指定初始頁面的前端
activity類處於android.app包中,繼承體系以下:java
1.java.lang.Objectandroid
2.android.content.Context程序員
3.android.app.ApplicationContext數據庫
4.android.app.Activity網絡
activity是單獨的,用於處理用戶操做。幾乎全部的activity都要和用戶打交道,因此activity類建立了一個窗口,開發人員能夠經過setContentView(View)接口把UI放到activity建立的窗口上,當 activity指向全屏窗口時,也能夠用其餘方式實現:做爲漂浮窗口(經過windowIsFloating的主題集合),或者嵌入到其餘的 activity(使用ActivityGroup)。大部分的Activity子類都須要實現如下兩個接口:app
onCreate(Bundle)接口是初始化activity的地方. 在這兒一般能夠調用setContentView(int)設置在資源文件中定義的UI, 使用findViewById(int) 能夠得到UI中定義的窗口.ide
onPause()接口是使用者準備離開activity的地方,在這兒,任何的修改都應該被提交(一般用於ContentProvider保存數據).函數
爲了可以使用Context.startActivity(),全部的activity類都必須在AndroidManifest.xml文件中定義有相關的「activity」項。網站
而對於安卓程序須要首先運行的activity即下文提到的「main」activity,則須要AndroidManifest.xml文件中的<intent-filter>元素添加這麼兩句:
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<action>元素指定這是一個"main"入口點對這個應用程序。<category>元素指定,這個activity應該被列入系統應用程序列表中(爲了容許用戶啓動這個activity)。
若是你但願應用程序自包含,而且不但願別的應用程序激活它的activities,那麼你不須要任何其它intent filters。只有一個activity應該有「main"動做和」launcher「分類,就像前面這個例子。你不但願被其它應用程序訪問原Activities應該沒有intent filters並且你能啓動他們經過本身顯示的intent。
但是,若是你但願你的activity響應影含的intents,從其它應用程序(和你本身的),那麼你必須爲這個activity定義額外的intent filters。每一種你但願響應的類型的intent,你必須包含<intent-filter>,包含<action>元素,可選的,一個<category>元素而且/或一個<data>元素。這些元素指定你的activity能響應的intent的類型。
[若是全部的activity都包含此過濾器(即上面的filter),則默認首個activity爲初始activity]
過濾器使用的具體過程參見如下描述,可幫助記憶和理解:
當寫好的應用發佈到手機上以後,當雙擊」抽屜「裏該應用的圖標時,系統會將這個點擊時間包裝成一個Intent,該Intent包含兩個參數,如上所述的兩個參數被傳遞給應用以後,在應用的功能清單文件中尋找與該意圖匹配的意圖過濾器,若是匹配成功,找到相匹配的意圖過濾器所在的Activity元素,再根據<activity>元素的」name「屬性來尋找其對應的Activity類。接着Android操做系統建立該Activity類的實例對象,對象建立完成以後,會執行到該類的onCreate方法,此onCreate方法是重寫父類Activity的onCreate方法而實現的。onCreate方法用來初始化Activity實例對象。以下是helloWorld.java類中的onCreate方法的代碼:
public void onCreate (Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
其中super.onCreate(savedInstanceState)的做用是調用其父類Activity的onCreate方法來實現對界面的圖畫繪製工做。在實現本身定義的Activity子類的onCreate方法時必定要記得調用該方法,以確保可以繪製界面。
setContentView(R.layout.main)的做用是加載一個界面。該方法中傳入的參數是」R.layout.main「,其含義爲R.java類中靜態內部類layout的靜態常量main的值,而改值是一個指向res目錄下的layout子目錄下的main.xml文件的標識符。所以表明着顯示main.xml所定義的畫面
一個Activity是一個應用程序組件,提供一個屏幕,用戶能夠用來交互爲了完成某項任務,例如撥號、拍照、發送email、看地圖。每個activity被給予一個窗口,在上面能夠繪製用戶接口。窗口一般充滿屏幕,但也能夠小於屏幕而浮於其它窗口之上。
一個應用程序一般由多個activities組成,他們一般是鬆耦合關係。一般,一個應用程序中的activity被指定爲"main"activity,當第一次啓動應用程序的時候呈現給用戶的那個activity。每個activity而後能夠啓動另外一個activity爲了完成不一樣的動做[該動做經過intent完成,詳見安卓之Activity信使——intent文]。每一次一個activity啓動,前一個activity就中止了,可是系統保留activity在一個棧上(「back stack」)。當一個新activity啓動,它被推送到棧頂,取得用戶焦點。Back Stack符合簡單「後進先出」原則,因此,當用戶完成當前activity而後點擊back按鈕,它被彈出棧(而且被摧毀),而後以前的activity恢復。
當一個activity因新的activity啓動而中止,它被通知這種狀態轉變經過activity的生命週期回調函數。有許多回調函數一個activity可能會收到,源於它本身的狀態變化-不管系統建立它、中止它、恢復它、摧毀它-而且每一個回調提供你完成適合這個狀態的指定工做的機會。例如,當中止的時候,你的activity應該釋聽任何大的對象,例如網絡數據庫鏈接。當activity恢復,你能夠從新得到必要的資源和恢復被中斷的動做。這些狀態轉換都是activity的生命週期的部分。
和 J2ME 的 MIDlet 同樣,在 android 中,Activity 的生命週期交給系通通一管理。與 MIDlet 不一樣的是安裝在 android 中的全部的 Activity 都是平等的。
在 android 中,Activity 擁有四種基本狀態:
Active/Runing一個新 Activity 啓動入棧後,它在屏幕最前端,處於棧[關於Activity棧的概念,可見下文說明]的最頂端,此時它處於可見並可和用戶交互的激活狀態。
Paused 當 Activity 被另外一個透明或者 Dialog 樣式的 Activity 覆蓋時的狀態。此時它依然與窗口管理器保持鏈接,系統繼續維護其內部狀態,因此它仍然可見,但它已經失去了焦點故不可與用戶交互。
Stoped 當 Activity 被另一個 Activity 覆蓋、失去焦點並不可見時處於 Stoped狀態。
Killed Activity 被系統殺死回收或者沒有被啓動時處於 Killed狀態。
當一個 Activity 實例被建立、銷燬或者啓動另一個 Activity 時,它在這四種狀態之間進行轉換,這種轉換的發生依賴於用戶程序的動做。下圖說明了 Activity 在不一樣狀態間轉換的時機和條件:
如上所示,Android 程序員能夠決定一個 Activity 的「生」,但不能決定它的「死」,也就時說程序員能夠啓動一個 Activity,可是卻不能手動的「結束」一個 Activity。當你調用 Activity.finish()方法時,結果和用戶按下 BACK 鍵同樣:告訴 Activity Manager 該 Activity 實例完成了相應的工做,能夠被「回收」[ 根據下文的意思,應該是調用finish方法時只能使Activity進入Stoped狀態 ]。隨後 Activity Manager 激活處於棧第二層的 Activity 並從新入棧,同時原 Activity 被壓入到棧的第二層,從 Active 狀態轉到 Paused 狀態。例如:從 Activity1 中啓動了 Activity2,則當前處於棧頂端的是 Activity2,第二層是 Activity1,當咱們調用 Activity2.finish()方法時,Activity Manager 從新激活 Activity1 併入棧,Activity2 從 Active 狀態轉換 Stoped 狀態,Activity1. onActivityResult(int requestCode, int resultCode, Intent data)方法被執行,Activity2 返回的數據經過 data參數返回給 Activity1。
Android 是經過一種 Activity 棧的方式來管理 Activity 的,一個 Activity 的實例的狀態決定它在棧中的位置。處於前臺的 Activity 老是在棧的頂端,當前臺的 Activity 由於異常或其它緣由被銷燬時,處於棧第二層的 Activity 將被激活,上浮到棧頂。當新的 Activity 啓動入棧時,原 Activity 會被壓入到棧的第二層。一個 Activity 在棧中的位置變化反映了它在不一樣狀態間的轉換。Activity 的狀態與它在棧中的位置關係以下圖所示:
如上所示,除了最頂層即處在 Active 狀態的 Activity 外,其它的 Activity 都有可能在系統內存不足時被回收,一個 Activity 的實例越是處在棧的底層,它被系統回收的可能性越大。系統負責管理棧中 Activity 的實例,它根據 Activity 所處的狀態來改變其在棧中的位置。
在 android.app.Activity類中,Android 定義了一系列與生命週期相關的方法,在咱們本身的 Activity 中,只是根據須要複寫須要的方法,Java 的多態性會保證咱們本身的方法被虛擬機調用,這一點與 J2ME 中的 MIDlet 相似。
public class OurActivity extends Activity {
protected void onCreate(Bundle savedInstanceState);
protected void onStart();
protected void onResume();
protected void onPause();
protected void onStop();
protected void onDestroy();
}
這些方法的說明以下:
protected void onCreate(Bundle savedInstanceState)一個 Activity 的實例被啓動時調用的第一個方法。通常狀況下,咱們都覆蓋該方法做爲應用程序的一個入口點,在這裏作一些初始化數據、設置用戶界面等工做。大多數狀況下,咱們都要在這裏從 xml 中加載設計好的用戶界面。例如:
setContentView(R.layout.main);
固然,也可從 savedInstanceState中讀咱們保存到存儲設備中的數據,可是須要判斷 savedInstanceState是否爲 null,由於 Activity 第一次啓動時並無數據被存貯在設備中:
if(savedInstanceState!=null){
savedInstanceState.get("Key");
}
protected void onStart()該方法在 onCreate() 方法以後被調用,或者在 Activity 從 Stop 狀態轉換爲 Active 狀態時被調用。
protected void onResume()在 Activity 從 Pause 狀態轉換到 Active 狀態時被調用。
protected void onPause()在 Activity 從 Active 狀態轉換到 Pause 狀態時被調用。
protected void onStop()在 Activity 從 Active 狀態轉換到 Stop 狀態時被調用。通常咱們在這裏保存 Activity 的狀態信息。
protected void onDestroy()在 Active 被結束時調用,它是被結束時調用的最後一個方法,在這裏通常作些釋放資源,清理內存等工做。
此外,Android 還定義了一些不經常使用的與生命週期相關的方法可用:
protected void onPostCreate(Bundle savedInstanceState);
protected void onRestart();
protected void onPostResume();
Android 提供的文檔詳細的說明了它們的調用規則。
在 android 中建立一個 Activity 是很簡單的事情,編寫一個繼承自 android.app.Activity的 Java 類並在 AndroidManifest.xml聲明便可。下面是一個爲了研究 Activity 生命週期的一個 Activity 實例(工程源碼見下載):
Activity 文件:
public class EX01 extends Activity {
private static final String LOG_TAG = EX01.class.getSimpleName();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Log.e(LOG_TAG, "onCreate");
}
@Override
protected void onStart() {
Log.e(LOG_TAG, "onStart");
super.onStart();
}
@Override
protected void onResume() {
Log.e(LOG_TAG, "onResume");
super.onResume();
}
@Override
protected void onPause() {
Log.e(LOG_TAG, "onPause");
super.onPause();
}
@Override
protected void onStop() {
Log.e(LOG_TAG, "onStop");
super.onStop();
}
@Override
protected void onDestroy() {
Log.e(LOG_TAG, "onDestroy ");
super.onDestroy();
}
}
AndroidManifest.xml 中經過 <activity> 節點說明 Activity,將 apk 文件安裝後,系統根據這裏的說明來查找讀取 Activity,本例中的說明以下:
<activity android:name=".EX01" android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Activity.startActivity()方法能夠根據傳入的參數啓動另一個 Activity:
Intent intent =new Intent(CurrentActivity.this,OtherActivity.class);
startActivity(intent);
固然,OtherActivity一樣須要在 AndroidManifest.xml 中定義。[關於intent的內容將在安卓之Activity信使——intent文中介紹]