標籤:
一、什麼是activity
Activity 是使用者介面程式,原則上它會提供給使用者一個互動介面功能。它是 android 應用程式的準系統單元。Activity 本身是沒有介面的。所以activity類建立了一個視窗,開發人員可以通過setContentView(View)介面把UI放到activity建立的視窗上,當activity指向全屏視窗時,也可以用其他方式實現:作為漂浮視窗(通過windowIsFloating的主題集合),或者嵌入到其他的activity(使用ActivityGroup)。activity是單獨的,用於處理使用者操作。幾乎所有的activity都要和使用者打交道,
【Activity】
一個Activity是一個應用程式組件,提供一個螢幕,使用者可以用來互動為了完成某項任務,例如撥號、拍照、發送email、看地圖。每一個activity被給予一個視窗,在上面可以繪製使用者介面。視窗通常充滿螢幕,但也可以小於螢幕而浮於其它視窗之上。
一個應用程式通常由多個activities組成,他們通常是松耦合關係。通常,一個應用程式中的activity被指定為"main"activity,當第一次啟動應用程式的時候呈現給使用者的那個activity。每一個activity然後可以啟動另一個activity為了完成不同的動作。每一次一個activity啟動,前一個activity就停止了,但是系統保留activity在一個棧上(“back stack”)。當一個新activity啟動,它被推送到棧頂,取得使用者焦點。Back Stack符合簡單“後進先出”原則,所以,當使用者完成當前activity然後點擊back按鈕,它被彈出棧(並且被摧毀),然後之前的activity恢複。
當一個activity因新的activity啟動而停止,它被通知這種狀態轉變通過activity的生命週期回呼函數。有許多回呼函數一個activity可能會收到,源於它自己的狀態變化-無論系統建立它、停止它、恢複它、摧毀它-並且每個回調提供你完成適合這個狀態的指定工作的機會。例如,當停止的時候,你的activity應該釋放任何大的對象,例如網路資料庫串連。當activity恢複,你可以重新獲得必要的資源和恢複被中斷的動作。這些狀態轉換都是activity的生命週期的部分。
【Creating an Activity】
建立一個activity,你必須建立一個Activity的子類(或者一個Activity的子類的子類)。在你的子類中,你需要實現系統回調的回調方法,當activity在它的生命週期的多種狀態中轉換的時候,例如當activity被建立、停止、恢複或摧毀。兩個最重要的回調方法是:
onCreate()你必須實現這個方法。系統調用它當建立你的activity的時候。在你的實現中,你應該初始化你的activity的基本的組件。更重要的是,這裡就是你必須調用setContentView()來定義activity使用者介面而已的地方。onPause()系統調用這個方法當使用者離開你的activity(雖然不總是意味著activity被摧毀)。這通常是你應該提交任何變化,那此將會超越user session而存在的(因為使用者可能不再回來)。
有若干其它生命週期回呼函數你應該使用為了提供一個流暢的使用者體驗,並表操作異常中斷會引起你的activity被中斷甚至被摧毀。
1、Implementing a user interface
一個activity的使用者介面被一個層次化的視圖提供--繼承於View類的對象。每個View控制activity視窗中的一個特定矩形地區並且能響應使用者互動。例如,一個view可能是個button,初始化動作當使用者觸摸它的時候。
Android提供大量預定義的view,你可以使用來設計和組件你的布局。“Widgets”是一種給螢幕提供可視化(並且互動)元素的view,例如按鈕、檔案域、複選框或者僅僅是映像。“Layouts”是繼承於ViewGroup的View,提供特殊的布局模型為它的子view,例如線程布局、格子布局或相關性布局。你可以子類化View和ViewGroup類(或者存在的子類)來建立自己的widget和而已並且應用它們到你的activity布局中。
最普通的方法是定義一個布局使用view加上XML布局檔案儲存在你的程式資源裡。這樣,你可以單獨維護你的使用者介面設計,而與定義activity行為的代碼無關。你可以設定布局作為UI使用setContentView(),傳遞資源布局的資源ID。可是,你也可以建立新Views在你的activity代碼,並且建立一個view層次通過插入新Views到ViewGroup,然後使用那個布局通過傳遞到根ViewGroup給setContentView()。
【Declaring the activity in the manifest】
你必須聲明你的activity在manifest檔案為了它可以被系統訪問。要聲明你的activity,開啟你的manifest檔案,添加一個<activity>元素作為<application>元素的子項目。例如:
【Using intent filters】
一個<activity>元素也能指定多種intent filters--使用<inetent-filter>元素--為了聲明其它應用程式可以啟用它。
當你建立一個新應用程式使用Android SDK工具,存根activity自動為你建立,包含一個intent filter,聲明了activity響應"main"動作,並且應該被 放置 在"launcher"分類。Intent filter看起來像這個樣子。
<action>元素指定這是一個"main"進入點對這個應用程式。<category>元素指定,這個activity應該被列入系統應用程式列表中(為了允許使用者啟動這個activity)。
如果你希望應用程式自包含,並且不希望別的應用程式啟用它的activities,那麼你不需要任何其它intent filters。只有一個activity應該有“main"動作和”launcher“分類,就像前面這個例子。你不希望被其它應用程式訪問原Activities應該沒有intent filters而且你能啟動他們通過自己顯示的intent。
可是,如果你希望你的activity響應影含的intents,從其它應用程式(和你自己的),那麼你必須定義額外的intent filters為這個activity。每一種你希望響應的類型的intent,你必須包含<intent-filter>,包含<action>元素,可選的,一個<category>元素並且/或一個<data>元素。這些元素指定你的activity能響應的intent的類型。
【Starting an Activity】
你可以開啟另一個activity通過startActivity(),傳遞一個Intent描述了你希望啟動的Activity。Intent指定要麼準備的activity你希望啟動或描述你希望完成的動作(作業系統選擇合適的activity為你,可能來自定不同的應用程式)。一個intent可以傳輸小量資料被啟動的activity使用。
完全工作在你的應用程式之內,你將經常需要簡單的啟動一個未知的activity。你可以這麼通過建立一個intent顯示的定義你希望啟動的activity,使用類名。例如,下面顯示一個activity怎麼啟動另一個activity命名為SignInActivity:
可是,你的應用程式或許希望執行一些動作,例如發送一份郵件、檔案訊息或者狀態更新,使用你的activity的資料。在這種情況下,你的應用程式或許沒有它自己的activity來完成這個動作,因此你可以促使裝置上其它應用程式提供的activity來完成你的動作。這才是intent真正有價值的地方--你可以建立一個intent描述一個你希望執行的動作,然後系統啟動一個合適的activity從其它應用程式。如果有多種activities可以處理這個intent,那麼 使用者可以選擇哪一個來執行。例如,如果你希望允許使用者發送郵件,你可以建立下面的Intent:
EXTRA_EMAIL額外的添加給intent一個字串數組指定email地址,當一個郵件應用程式響應這個intent的時候,它讀取這些字串數組並且放置他們到相應欄位。在這種情況下,email應用程式的activity啟動並且當使用者執行完,你的activity恢複。
【Starting an activity for a result】
有時,你或許希望接收一個結果從你啟動的activity。在這種情況下,開啟這個activity通過startActivityForResult()(而不是startActivity())。然後從隨後的activity接收結果,實現onActiviryResult()回呼函數。當隨後的activity完成,它返回一個結果給你的onActivityResult()函數通過一個intent。
例如,或許你希望使用者選擇他們中的一個連絡人,所以你的activity可以對這個連絡人做些事情。下面是你怎麼建立這樣一個Intent和操作結果:
這個例子展現了基本的邏輯你應該使用的在你的onActivityResult()函數中,為了操作一個activity的結果。第一個條件檢測是否請求成功--如果是,那麼 resultCode將會是RESULT_OK--並且是否這個請求是否是這個響應是響知道--在這種情況下,requestCode匹配第二個參數用startActivityForResult()的參數。在那裡,代碼操作activity結果通過查詢返回在intent中的資料(data參數)。
將發生的是,一個ContentResolver實現查詢content provider,返回一個Cursor允許讀查詢的資料。
【Shut Down an Activity】
你可以關閉一個activity通過調用自身的finish()方法。你也可以關閉一個獨立的activity你之前啟動的通過finiActivity()。
注意:在大多數情況下,你不應該顯示結果一個activity使用這些方法。正在下文所討論的關於activity的生命週期,Android系統管理一個activity的生命週期為你,所以你不需要結果你自己的activity。調用這些函數對使用者體驗有害並且只有在你決對不希望使用者返回到這個activity的情況下。
二、activity生命週期
public class Activity extends ApplicationContext {protected void onCreate(Bundle savedInstanceState); protected void onStart(); protected void onRestart(); protected void onResume(); protected void onPause(); protected void onStop(); protected void onDestroy();}
由圖可知:
在一個Activity正常啟動過程中,這些方法調用的順序是onCreate -> onStart -> onResume;在Activity被kill掉的時候方法順序是onPause -> onStop -> onDestroy,此為一個完整的Lifecycle。那麼對於中斷處理(比如電話來了),則是onPause -> onStop,恢複時onStart -> onResume;如果當前應用程式的是一個Theme為Translucent(半透明) 或者Dialog 的Activity那麼中斷就是onPause ,恢複的時候onResume。
那麼對於”Other app need memory”,就是我們手機在運行一個應用程式的時候,有可能打進來電話發進來簡訊,或者沒有電了,這時候程式都會被中斷,優先去服務電話的準系統,另外系統也不允許你佔用太多資源,至少要保證一些功能(比如電話),所以資源不足的時候也就有可能被kill掉。
方法在系統中的作用及我們應該做什麼:
onCreate:在這裡建立介面,做一些資料的初始化工作;
onStart: 到這一步變成“使用者可見不可互動”的狀態;
onResume:變成和使用者可互動的,(在Activity棧系統通過棧的方式管理這些Activity,即當前Activity在棧的最上端,運行完彈出棧,則回到上一個Activity);
onPause:到這一步是可見但不可交互的,系統會停止動畫等消耗CPU的事情。從上文的描述已經知道,應該在這裡儲存你的一些資料,因為這個時候你的程式的優先順序降 低,有可能被系統收回。在這裡儲存的資料,應該在onResume裡讀出來。
onStop:變得不可見 ,被下一個activity覆蓋了
onDestroy:這是Activity被kill前最後一個被呼叫者法了,可能是其他類調用finish方法或者是系統為了節省空間的將它暫時性的幹掉,可以用isFinishing()來判斷它,如果你有 一個Progress Dialog線上程中運行,請在onDestroy裡把他cancel掉,不然等線程結束的時候,調用Dialog的cancel方法會拋異常。
onPause,onstop, onDestroy,三種狀態下 activity都有可能被系統kill 掉。
三、Activity之間的通訊
在 Android 中,不同的 Activity 執行個體可能運行在一個進程中,也可能運行在不同的進程中。因此我們需要一種特別的機制協助我們在 Activity 之間傳遞訊息。Android 中通過 Intent 對象來表示一條訊息,一個 Intent 對象不僅包含有這個訊息的目的地,還可以包含訊息的內容,這好比一封 Email,其中不僅應該包含收件地址,還可以包含具體的內容。對於一個 Intent 對象,訊息“目的地”是必須的,而內容則是可選項。
Intent負責對操作的動作、動作涉及資料、附加資料進行描述,Android則根據此Intent的描述,負責找到對應的組件,將 Intent傳遞給調用的組件,並完成組件的調用。因此,Intent在這裡起著一個媒體中介的作用,專門提供組件互相調用的相關資訊,實現調用者與被調用者之間的解耦。
在應用中,我們可以以兩種形式來使用Intent:
直接Intent:指定了component屬性的Intent(調用setComponent(ComponentName)或者setClass(Context, Class)來指定)。通過指定具體的組件類,通知應用啟動對應的組件。
間接Intent:沒有指定comonent屬性的Intent。這些Intent需要包含足夠的資訊,這樣系統才能根據這些資訊,在在所有的可用組件中,確定滿足此Intent的組件。
對於直接Intent,Android不需要去做解析,因為目標組件已經很明確。
Android需要解析的是那些間接Intent,通過解析,將 Intent映射給可以處理此Intent的Activity、IntentReceiver或Service。Intent解析機制主要是通過尋找登入在AndroidManifest.xml中的所有IntentFilter及其中定義的Intent,最終找到匹配的Intent。
四、Activity 的 Intent Filter
Intent Filter 描述了一個組件願意接收什麼樣的 Intent 對象,Android 將其抽象為 android.content.IntentFilter 類。在 Android 的 AndroidManifest.xml 設定檔中可以通過 <intent-filter >節點為一個 Activity 指定其 Intent Filter,以便告訴系統該 Activity 可以響應什麼類型的 Intent。
當使用 startActivity(intent) 來啟動另外一個 Activity 時,如果直接指定 intent 對象的 Component 屬性,那麼 Activity Manager 將試圖啟動其 Component 屬性指定的 Activity。否則 Android 將通過 Intent 的其它屬性從安裝在系統中的所有 Activity 中尋找與之最匹配的一個啟動,如果沒有找到合適的 Activity,應用程式會得到一個系統拋出的異常。這個匹配的過程如下:
五、Activity的棧式管理
Android針對Activity的管理使用的是棧,就是說某一個時刻只有一個Activity處在棧頂,當這個Activity被銷毀後,下面的Activity才有可能浮到棧頂,或者有一個新的Activity被建立出來,則舊的Activity就被壓棧沉下去了。Activity是Android程式的表現層。程式的每一個顯示螢幕就是一個Activity。正在啟動並執行Activity處在棧的最頂端,它是運行狀態的。
當在程式中調用 Activity.finish()方法時,結果和使用者按下 BACK 鍵一樣:它告訴 Activity Manager該Activity執行個體可以被“回收”。隨後 Activity Manager 啟用處於棧第二層的 Activity ,把原 Activity 壓入到棧的第二層,從 Running 狀態轉到 Paused 狀態。
六、Activity的載入模式
standard、singleTop、singleTask、singleInstance(其中前兩個是一組、後兩個是一組),預設為standard
standard:就是intent將發送給新的執行個體,所以每次跳轉都會產生新的activity。
singleTop:也是發送新的執行個體,但不同standard的一點是,在請求的Activity正好位於棧頂時(配置成singleTop的Activity),不會構造新的執行個體
singleTask:和後面的singleInstance都只建立一個執行個體,當intent到來,需要建立設定為singleTask的Activity的時候,系統會檢查棧裡面是否已經有該Activity的執行個體。如果有直接將intent發送給它。
singleInstance:
首先說明一下task這個概念,Task可以認為是一個棧,可放入多個Activity。比如啟動一個應用,那麼Android就建立了一個Task,然後啟動這個應用的入口Activity,那在它的介面上調用其他的Activity也只是在這個task裡面。那如果在多個task中共用一個Activity的話怎麼辦呢。舉個例來說,如果開啟一個導遊服務類的應用程式,裡面有個Activity是開啟GOOGLE地圖的,當按下home鍵退回到主菜單又啟動GOOGLE地圖的應用時,顯示的就是剛才的地圖,實際上是同一個Activity,實際上這就引入了singleInstance。singleInstance模式就是將該Activity單獨放入一個棧中,這樣這個棧中只有這一個Activity,不同應用的intent都由這個Activity接收和展示,這樣就做到了共用。當然前提是這些應用都沒有被銷毀,所以剛才是按下的HOME鍵,如果按下了返回鍵,則無效。
七、Activity的跳轉
Activity跳轉,無返回結果
這是最簡單的Activity跳轉方式。從一個Activity啟動另一個Activity,直接startActivity(new Intent(當前Activity.this, 下一Activity.class))。
Activity跳轉,返回資料/結果
需要返回資料或結果的,則使用startActivityForResult (Intent intent, int requestCode),requestCode的值是自訂的,用於識別跳轉的目標Activity。跳轉的目標Activity所要做的就是返回資料/結果,setResult(int resultCode)只返回結果不帶資料,或者setResult(int resultCode, Intent data)兩者都返回!而接收返回的資料/結果的處理函數是onActivityResult(int requestCode, int resultCode, Intent data),這裡的requestCode就是startActivityForResult的requestCode,resultCode就是setResult裡面的resultCode,返回的資料在data裡面。
** 注意,在setResult後,要調用finish()銷毀當前的Activity,否則無法返回到原來的Activity,就無法執行原來Activity的onActivityResult函數,看到當前的Activity沒反應。 本人是個新手,沒什麼經驗,如發現有錯誤或者什麼好的建議,歡迎指正!請多多指教!
android學習——activity總結