Android開發(fā)入門:四大組件之Activities
1、定義
Activity是為用戶提供可視化界面并可以與用戶交互的組件。
2、概述
應(yīng)用程序通常是多個(gè)松散并相互綁定的Activity組成。一般,用戶***啟動(dòng)應(yīng)用時(shí),將啟動(dòng)一個(gè)被指定為main的Activity。每個(gè)Activity都可以啟動(dòng)另一個(gè)Activity,以執(zhí)行不同的動(dòng)作。每次啟動(dòng)一個(gè)新的Activity,以前的Activity停止,但在系統(tǒng)堆棧保留Activity(“回棧”)。一個(gè)新的Activity啟動(dòng)時(shí),它將當(dāng)前Activity壓到棧里面并取得用戶的焦點(diǎn)。回堆棧遵守基本的“后進(jìn)先出”的堆棧機(jī)制。當(dāng)用戶在當(dāng)前Activity,按下返回按鈕,則當(dāng)前彈出堆棧(并銷毀)和恢復(fù)以前的Activity。
Activity停止是因?yàn)橐粋€(gè)新的Activity開始,通過活動(dòng)的生命周期回調(diào)方法,通知這種狀態(tài)發(fā)送變化。一個(gè)Activity可能會收到多個(gè)回調(diào) 方法,當(dāng)狀態(tài)發(fā)生變化時(shí).產(chǎn)生,停止,恢復(fù),銷毀,這些回調(diào)在適當(dāng)?shù)臅r(shí)機(jī)提供給您做相應(yīng)工作的機(jī)會。例如,停止時(shí),你的Activity應(yīng)該釋放大型對 象,如網(wǎng)絡(luò)或數(shù)據(jù)庫連接。恢復(fù)Activity時(shí),你可以重新獲得必要的資源和恢復(fù)被中斷的Activity。這些狀態(tài)轉(zhuǎn)換是所有的Activity程序 周期的一部分。
3、創(chuàng)建Activity
a. 概述
要生成一個(gè)Activity,你必須生成一個(gè)Activity子類Activity(或已有的子類)。在你的子類中,創(chuàng)建,停止,恢復(fù)或銷毀 Acitivty時(shí),你需要實(shí)現(xiàn)回調(diào)方法,系統(tǒng)調(diào)用時(shí),用這些方法在Activity生命周期的各種狀態(tài)之間的轉(zhuǎn)換。兩個(gè)最重要的回調(diào)方法是:
onCreate():必須實(shí)現(xiàn)這個(gè)方法。生成Activity時(shí)系統(tǒng)調(diào)用。在你實(shí)現(xiàn)中,你應(yīng)該初始化您的Activity中的組件。最重要的是,這是你必須調(diào)用 setContentView() 定義Activity的用戶界面的布局。
onPause():當(dāng)用戶離開你的Activity時(shí)候(盡管它并不總是意味著被銷毀Activity),系統(tǒng)調(diào)用此方法。通常如果你需要保持當(dāng)前會話的話,你所有的改動(dòng)都應(yīng)在這提交(因?yàn)橛脩艨赡懿环祷兀?/p>
還有其他幾個(gè)生命周期回調(diào)方法,你應(yīng)該使用這些方法處理Activity與導(dǎo)致使Activity必須停止,甚至銷毀的突發(fā)中斷之間的事情,來提供流暢的用戶體驗(yàn)。所有的生命周期回調(diào)方法將在稍后討論,在有關(guān) 管理Activity生命周期部分。
b. 實(shí)現(xiàn)用戶界面
一個(gè)Activity的用戶界面是由一組按層派生視圖類-View的視圖對象組成。每個(gè)視圖控制Activity窗口的特定矩形空間,以響應(yīng)用戶交互。例如,一個(gè)視圖可能是一個(gè)按鈕,當(dāng)用戶觸摸它啟動(dòng)一個(gè)操作。
Android提供了一些現(xiàn)成的視圖,你可以用它來設(shè)計(jì)和組織布局。“Widgets”就是視圖-view,他提供一個(gè)可視的可交互的屏幕元素,如按鈕,文本字段,復(fù)選框,或只是一個(gè)圖象。“布局”是從視圖組-ViewGroup派生的,提供了對子視圖特殊的布局模式,如線性布局,網(wǎng)格布局,或相對布局的視圖組。還可以繼承視圖類-View和視圖組 - ViewGroup(或現(xiàn)有的子類)來創(chuàng)建自己的Widgets和布局,并將其應(yīng)用到您的Activity布局中。
最常見的方式來定義一個(gè)布局,是一個(gè)XML布局文件保存您的應(yīng)用程序資源。這種方式,你可以單獨(dú)從源代碼中維護(hù)你的用戶界面設(shè)計(jì)以及定義Activity 的行為。你可以通過setContentView()設(shè)置您的Activity的UI布局 ,傳入布局的資源ID。或者,你也可以在Activity代碼中生成新的視圖-View,新建立一個(gè)視圖 - View層次結(jié)構(gòu)插入到視圖組-ViewGroup ,然后傳入根視圖組-ViewGroup給setContentView()進(jìn)行布局。
c. 在manifest文件中聲明Activity
要在系統(tǒng)中使用Activity,您必須在manifest文件中聲明您的Activity。打開你的manifest文件,并添加 <activity-element>>作為 <application><application> 元素一個(gè)子元素。例如:
- <manifest ... >
- <application ... >
- <activity android:name=".ExampleActivity" />
- ...
- </application ... >
- ...
- </manifest >
在這個(gè)元素可以包含其他一些屬性,包括定義屬性,如Activity的標(biāo)簽,圖標(biāo)的Activity,或Activity的主題UI風(fēng)格。 屬性android:name 是唯一需要的屬性,它指定Activity的類名。一旦你發(fā)布你的應(yīng)用程序,你不應(yīng)該改變這個(gè)名字,因?yàn)槿绻@樣做,你可能會破壞一些功能,如應(yīng)用程序的快捷方式。
d. 使用intent過濾器
一個(gè) <activity> 元素也可使用 <intent-filter>的元素指定的各種intent過濾器,以說明其他應(yīng)用程序組件可以如何激活它。
當(dāng)你使用Android SDK工具為您創(chuàng)建一個(gè)新的應(yīng)用,<activity>標(biāo)簽下自動(dòng)包括用于聲明Activity響應(yīng)main的動(dòng)作的intent過濾器和用于啟動(dòng)的lancher分類。intent 過濾器看起來像這樣:
- <activity android:name=".ExampleActivity" android:icon="@drawable/app_icon">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
<action> 元素指定應(yīng)用程序main的入口。 <category> 元素指定系統(tǒng)的activity列表上應(yīng)用啟動(dòng)的Activity,(允許用戶啟動(dòng)這個(gè)Activity)。
如果你打算讓您的應(yīng)用程序成為一個(gè)獨(dú)立的應(yīng)用,不允許其他應(yīng)用程序啟動(dòng)應(yīng)用中的Activity,那你就不需要其他的intent過濾器。 如前面示例所示,只有一個(gè)Activity帶有main動(dòng)作和launcher類別。你 不讓其他Activity用于其他應(yīng)用程序,那他們不應(yīng)有任何intent過濾器,你必須顯示的調(diào)用intent啟動(dòng)他們。
但是,如果您希望您的 Activity響應(yīng)其他應(yīng)用程序(和自己)的隱式intent,那么你必須在您的Activity中定義額外的intent過濾器。為了響應(yīng)你需要響應(yīng) 的每種intent,你必須包括 <intent-filter> ,其中包括一個(gè) <action> 元素的和一個(gè)可選的 <category> 元素和/或 <data> 元素。這些元素指定你的Activity可以響應(yīng)的intent類型。
4、啟動(dòng)Activity
你就可以通過調(diào)用 startActivity(android.content.Intent) startActivity()啟動(dòng)另一個(gè)Activity,它傳遞一個(gè)Intent描述你要啟動(dòng)的Activity。intent指定你要啟動(dòng)的 Activity,或描述要執(zhí)行的動(dòng)作類型(系統(tǒng)為您選擇合適的Activity,甚至可能是他應(yīng)用程序的Activity)。intent也可攜帶少量 數(shù)據(jù)被用于要啟動(dòng)的Activity。
在自己的應(yīng)用程序中,你會經(jīng)常需要簡單地啟動(dòng)一個(gè)已知的Activity。你可以使用類名來創(chuàng)建一個(gè)intent,明確定義你要啟動(dòng)的Activity。另 外,您的應(yīng)用程序可能還需要執(zhí)行一些動(dòng)作,例如發(fā)送電子郵件,文字信息,或狀態(tài)更新,使用Activity中的數(shù)據(jù)。在這種情況下,你的應(yīng)用程序可能無法 有其自身的Activity,執(zhí)行這些行動(dòng),所以你可以轉(zhuǎn)而利用設(shè)備上其他應(yīng)用程序提供的Activity為您執(zhí)行。這是intent真正有價(jià)值的地方 ——你可以創(chuàng)建一個(gè)描述了要執(zhí)行的一個(gè)動(dòng)作的intent,系統(tǒng)從另一個(gè)應(yīng)用程序啟動(dòng)的適當(dāng)Activity。
如果有多個(gè)Activity可以處理的intent,那么用戶可以選擇使用哪一個(gè)。例如,如果你想允許用戶發(fā)送電子郵件,你可以創(chuàng)建以下intent:
- Intent intent = new Intent(Intent.ACTION_SEND);
- intent.putExtra(Intent.EXTRA_EMAIL, recipientArray);
- startActivity(intent);
a. 啟動(dòng)activity的返回結(jié)果
有時(shí),您要取得你啟動(dòng)的Activity的結(jié)果。使用Activity的startActivityForResult()。然后在后續(xù)實(shí)現(xiàn)了 onActivityResult()回調(diào)方法的Activity中取得結(jié)果。后續(xù)Activity完成后,它會返回一個(gè)intent給您 onActivityResult()方法。
- private void pickContact() {
- / /根據(jù)CONTENT PROVIDER URI定義,建議一個(gè)用于選擇聯(lián)系人得 INTENT
- Intent intent = new Intent(Intent.ACTION_PICK, Contacts.CONTENT_URI);
- startActivityForResult(intent, PICK_CONTACT_REQUEST);
- }
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- / /如果請求正常(OK)并且請求是PICK_CONTACT_REQUEST
- if (resultCode == Activity.RESULT_OK && requestCode == PICK_CONTACT_REQUEST) {
- / /查詢 content provider 取得聯(lián)系人的名字
- Cursor cursor = getContentResolver().query(data.getData(),
- new String[] {Contacts.DISPLAY_NAME}, null, null, null);
- if (cursor.moveToFirst()) { // 游標(biāo)不為空
- int columnIndex = cursor.getColumnIndex(Contacts.DISPLAY_NAME);
- String name = cursor.getString(columnIndex);
- // 對選中名字的人進(jìn)行處理...
- }
- }
- }
5、關(guān)閉Actvity
您可以通過調(diào)用 finish()方法關(guān)閉Activity的。你也可以通過調(diào)用 finishActivity()關(guān)閉之前您啟動(dòng)的一個(gè)獨(dú)立的Activity 。注意:在大多數(shù)情況下,你應(yīng)該不需要顯示地使用這些方法結(jié)束Activity。在下面一節(jié)討論有關(guān)的Activity生命周期,Android系統(tǒng)為你管理Activity, 所以你不需要來自己結(jié)束Activity。調(diào)用這些方法可對用戶體驗(yàn)產(chǎn)生影響,只有你確定不想讓用戶返回此Activity實(shí)例時(shí)使用。
6、管理Activity生命周期
a. 實(shí)現(xiàn)生命周期函數(shù)

b. 保存activity狀態(tài)
恢復(fù)狀態(tài):在管理Activity生命周期中提到當(dāng)Activity暫停或者停止的時(shí)候,會保留Activity狀態(tài)。因?yàn)楫?dāng)他暫停或者停止的時(shí)候,內(nèi)存中 仍然有 Activity 對象,并且包含成員信息和當(dāng)前的狀態(tài),因此,在用戶模式下的任何對Activity的操作,在Activity返回到前臺的時(shí)候?qū)⒈贿€原("恢復(fù)狀態(tài)")。
重新運(yùn)行狀態(tài):在Activity變得不太穩(wěn)定的前,系統(tǒng)調(diào)用 onSaveInstanceState() 。該系統(tǒng)傳遞給其一個(gè) Bundle,您可以在其中以名稱-值對的形式保存為有關(guān)Activity的狀態(tài)信息,如使用方法 putString()和 putInt() 。然后,如果系統(tǒng)kill你的應(yīng)用進(jìn)程,當(dāng)用戶返回Activity,系統(tǒng)重建Activity時(shí),系統(tǒng)會同時(shí)傳給 onCreate() 和 onRestoreInstanceState() Bundle 。
使用這兩種方法,你可以從 Bundle 提取到保存的狀態(tài)信息來恢復(fù)Activity。如果沒有恢復(fù)的狀態(tài)信息, Bundle傳遞的是空(***創(chuàng)建Activity的情況)。由于onSaveInstanceState() 的默認(rèn)實(shí)施能保存UI的狀態(tài),如果要為保存額外的狀態(tài)信息而重寫此方法,那么在做任何工作之前,你一定要在實(shí)現(xiàn) onSaveInstanceState() 之前調(diào)用其超類方法。
同樣,如果你重寫它,你也應(yīng)該調(diào)用 onRestoreInstanceState()實(shí)現(xiàn)的超類方法,以此默認(rèn)實(shí)現(xiàn)恢復(fù)視圖狀態(tài)。因?yàn)?onSaveInstanceState() 不能保證被調(diào)用,所以當(dāng)用戶離開Activity,你應(yīng)該只使用它記錄Activity的瞬時(shí)狀態(tài)(UI的狀態(tài)),你不應(yīng)該用它來存儲持久數(shù)據(jù)。相 反,你應(yīng)該使用 onPause() 存儲持久數(shù)據(jù)(如保存到數(shù)據(jù)庫中的數(shù)據(jù))。

c. 處理配置改變
某 些設(shè)備配置在運(yùn)行時(shí)可以改變(如屏幕方向,鍵盤的可用性,和語言)。當(dāng)這種變化發(fā)生時(shí),Android重新運(yùn)行Activity(系統(tǒng)調(diào)用的 onDestroy(),然后立即調(diào)用的 onCreate())。這種行為旨在幫助您用您所提供的(如不同的屏幕方向和大小不同的布局)的替代資源進(jìn)行應(yīng)用程序自動(dòng)重載,以適應(yīng)新的配置。如果你 正確地設(shè)計(jì)Activity,以處理由于屏幕方向的變化帶來的重新啟動(dòng)并按照如上所述恢復(fù)Activity狀態(tài),那么您的應(yīng)用程序在Activity生命 周期中對于其他突發(fā)事件的應(yīng)對將更具彈性。處理重新啟動(dòng)來保存和恢復(fù)Activity狀態(tài)的一個(gè)的***方式是使用onSaveInstanceState()和onRestoreInstanceState()(或onCreate())。
7、協(xié)調(diào)Activities
在同一進(jìn)程中兩個(gè)Activity中,當(dāng)Activity A 啟動(dòng)Acivity B是產(chǎn)生的操作順序:
1.Activity A執(zhí)行onPause()方法;
2.Activity B按照onCreate(),OnStart(),onResume()的順序執(zhí)行方法。(ActivityB現(xiàn)在取得用戶的焦點(diǎn)。)
3.如果ActivityA已不再是顯示在屏幕上,它執(zhí)行方法onStop()。
這個(gè)可預(yù)測的生命周期回調(diào)順序,可讓您管理的從一個(gè)Activity到另一個(gè)Activity的轉(zhuǎn)換信息。例如,如果***個(gè)Activity停止時(shí)你必須寫數(shù)據(jù)庫 , 讓之后的Activity讀取數(shù)據(jù)庫,那么你應(yīng)該在onPause()期間寫數(shù)據(jù)庫而不是onStop()。
























