Activities 是一個程序的組件之一。它的主要功能是提供界面。
一個程序一般由多個Activity組成,各activities之間關系很松散,它們之間沒有直接的關聯。必須有一個activity被指定為主activity,它是程序啟動時首先顯示的界面。每個activity都可以隨意啟動其它的activity。每當一個activity被啟動,則前一個activity就被停止。一個程序中的所有啟動的activity都被放在一個棧中,所以被停止的activity並沒有銷毀,而在存於棧中。新啟動的activity先被存放於棧中,然後獲得輸入焦點。在當前活動的activity上點返回鍵,它被從棧中取出,然後銷毀,然後上一個activity被恢復。
當一個activity因為新的activity啟動而被停止時,它會收到狀態變化的通知,這樣的變化有多個,每個都會引起系統調用一個相應的回調方法以通知activity,這些回調方法被統稱為“生命周期回調方法”。這些回調方法分別在Activity被創建、停止、恢復、銷毀時被調用。
1 從類activity繼承。
2 實現“生命周期回調方法”
兩個最重要的方法是:
onCreate()--這個是必須實現的函數,在其中做初始化工作。記住:你必須在此函數中調用setContentView()函數的設置Activity的界面。
onPause()--這個雖然很重要,但不是要必須實現的。此函數在用戶離開Activity時被調用(這一般並不表示Activity要被銷毀了)。在這個函數中,你一般需要提交那些需保存狀態的數據(因為用戶可能不再返回到這個Activity)。
其它回調方法視情況實現。
此處的用戶界面指的就是activity上的控件們。所有的控件都從View類派生,所以可以把它們都稱為View。每個控件占據一個矩形區域。
控件又分為以下兩類:Widgets是完成特定功能的控件,比如button,text field,checkbox 等。Layouts是容納Widgets控件並進行排版的控件,當然,Layout中還可以容納Layout。Widgets從View類派生,Layouts從ViewGroup類中派生,開發者可以從View或ViewGroup派生創造自己的控件。
定義界面的最好的方法是使用XML格式的layout文件,它作為資源保存在工程中,可以在工程的res/layout下面找到這些XML文件。通過這種方式就做到了代碼與界分離。把layout 下的某個XML設置為某個Activity的界面,需調用Activity的setContentView(),把XML的資源ID作為參數傳入即可。
為了能讓系統操作你的Activity,你必須在工程的名單文件中聲明它。例如:
<manifest ... >
<application ... >
<activity Android:name=".ExampleActivity" />
...
</application ... >
...
</manifest >
當然有很多屬性可以設置給Activity,比如label,icon或主題等等。詳情請查看<activity>元素的說明。
注意看<activity android:name=".ExampleActivity"/>,看到activity name的值中,最前面有個”.”,如果你把它忘了,程序運行就會出錯,而你很難找出錯誤的原因。其次,不論你是Activity是只內部使用還是外部使用,都要去名單文件中注冊,否則依然會出現莫名其妙的錯誤,只是在內部使用時,不需要為acitivity增加意圖過濾器。可以為一個<activity>元素指定多個過慮器。使用<intent-filter>元素指定。intent過慮器的目的是告訴其它組件如何啟動這個Activity。當你使用ADT創建一個新工程時,根Activity被自動創建,它已具有兩個意圖過慮器,一個意圖過慮器聲明這個Activity負責響應“main”action;另一個過慮器聲明這個Activity須被置於”launcher”類別之下。一般是這個樣子:
<activityandroid:name=".ExampleActivity"android:icon="@drawable/app_icon">
<intent-filter>
<actionandroid:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<intent-filter>中就是過濾器們。<action>說明此Acitivity是程序的”main”入口,<category>指出這個Acitivity需要在系統的應用列表中列出。
如果你寫的程序中的Activity不需被其它程序調用,那麼不需為這個Activity增加任何意圖過濾器。但程序中必須有一個Activity被指定為”main” Action和”launcher” category。你自己程中的 Activity可以用更直接的方式調用。
然而,如果你想讓你的Activity被其它程序調用,那麼你需要為它增加意圖過濾器。這些過意圖濾器包括<action>,<category>以及<data>。這些元素指明了你的activity響應何種類型的intent。
你可以用startActivity()啟動一個activity,它有一個參數是intent,你需要在這個intent中指明要調用的activity。Intent中你可以明確地指定要啟動的activity,或只指定activity的類型,此時系統會為你挑選一個合適的activity,這個activity可能位於其它程序中,也可能位於你自己的程序中。Intent中可以帶一坨被新activity使用的數據(相當於參數傳遞)。
在你的程序內部,如果需要啟動一個內部的activity,你需在intent中明確指定新activity的類名。例如:
Intent intent = new Intent(this, SignInActivity.class);
startActivity(intent);
SignInActivity是要啟動的activity類。
然而,你的程序可能想執行自身沒有提供的功能,比如發出郵件,發送短信息等。此時,需要啟動其它程序提供的activity。此時就體現出intent的真正價值來了:它可以很容易地啟動其它程序提供的activity,你只需要在intent中指定你要執行的動作,然後調用 startActivity() ,系統就會跟據你的需要,為你選擇一個合適的activity,並啟動它。如果同時有多個activity可以執行這動作,那麼用戶可以選擇哪個被使用。例如,你想讓用戶發送一個電子郵件,你可以創建以下的Intent:
Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_EMAIL, recipientArray);
startActivity(intent);
putExtra()是設置擴充數據的,.EXTRA_EMAIL表明第二個參數recipientArray裡面放的是多個email地址。當發郵件的程序被啟動並接收到這個intent時,它就把郵件地址們放到它的Acitivity界面的“to”控件中。當用戶發送完畢返回時,你的activity就恢復運行(resume)。可以看到,啟動另外一個程序是多麼的容易。
有時,你可能想從你啟動的activity獲得其執行後返回的結果。此時你可以用方法startActivityForResult()來啟動新acitivity(不再是startActivity了)。然後,你的程序還需要定義回調方法onActivityResult()。當新activity運行結束時,它把一個intent返回給你的程序,這個intent是在onActivityResult()中被接收。
例如:你想讓用戶打開通訊錄,從中選擇一個聯系人,然後你取得用戶所選的聯系人,對之進行處理。以下是示例代碼:
private void pickContact() {
//Create anintent to "pick" a contact, as defined by the content provider URI
Intent intent =new Intent(Intent.ACTION_PICK, Contacts.CONTENT_URI);
startActivityForResult(intent, PICK_CONTACT_REQUEST);
}
@Override
protected void onActivityResult(int requestCode, intresultCode, Intent data) {
// If the requestwent well (OK) and the request was PICK_CONTACT_REQUEST
if (resultCode== Activity.RESULT_OK && requestCode == PICK_CONTACT_REQUEST) {
// Perform aquery to the contact's content provider for the contact's name
Cursorcursor = getContentResolver().query(data.getData(),new String[]{Contacts.DISPLAY_NAME}, null, null, null);
if(cursor.moveToFirst()) { // True if the cursor is not empty
intcolumnIndex = cursor.getColumnIndex(Contacts.DISPLAY_NAME);
String name =cursor.getString(columnIndex);
// Dosomething with the selected contact's name...
}
}
}
此例子展示了在onActivityResult()中的基本邏輯流程。首選檢查所啟動的Activity是否正確運行,resultCode為Activity.RESULT_OK表示正常,其次,查看requestCode是否與當時請求的一致,即是否為PICK_CONTACT_REQUEST。都通過後,開始操作返回的數據,也就是data參數。
Data是這樣處理的,用ContentResolver向內容提供者發出請求,這個請求會返回一個游標,通過這個游標讀取數據,這很像數據庫表的操作。要理解此處,請查閱Content Providers一節。
Activity可以內部調用finish()方法關閉它自己,也可以調用finishActivity()方法關閉其它的activity。
注意:大多數情況下,你不應主動結束一個activity。系統掌管著activity的生命,所以你也不必結束自己的activity。使用上述方法會破壞用戶體驗。除非你覺得很必要時,否則就不要做!