談Android四大組件之Activity篇

   前些天看瞭一個要上大四的學長寫的一篇Android實習生求職經歷,瞭解到一些關於Android的面試題,其中Android的四大組件(Activity、Service服務、Content Provider內容提供者、BroadcastReceiver廣播接收器)是最容易出面試題。除瞭應付面試,四大組件也是Android開發者必須要掌握的。於是Shamoo在網上收集瞭很多資料,將有用的整理起來。

 

  Activity的介紹

  Activity在Android應用中是一個單獨的界面,它上面可以顯示一些控件也可以監聽並處理用戶的事件做出響應。

  Activity之間是通過Intent進行通信。在Intent 的描述結構中,有兩個最重要的部分:動作和動作對應的數據。

  典型的動作類型有:MAIN(activity的門戶)、VIEW、PICK、EDIT 等。而動作對應的數據則以URI 的形式進行表示。例如:要查看一個人的聯系方式,你需要創建一個動作類型為VIEW 的intent,以及一個表示這個人的URI。

  與Intent相關的一類是IntentFilter,顧名思義就是意圖的過濾器,Activity可以通過IntentFilter響應相關的請求,其他不相關的請求則過濾掉。一個IntentFilter 則用於描述一個activity(或者IntentReceiver)能夠操作哪些intent。IntentFilter 需要在AndroidManifest.xml 中定義。通過解析各種Intent,從一個屏幕導航到另一個屏幕是很簡單的。當向前導航時,Activity 將會調用startActivity(Intent myIntent)方法。然後,系統會在所有安裝的應用程序中定義的IntentFilter 中查找,找到最匹配myIntent 的Intent 對應的activity。新的activity 接收到myIntent 的通知後,開始運行。當startActivity 方法被調用將觸發解析myIntent 的動作,這個機制提供瞭兩個關鍵好處:

  A、Activities 能夠重復利用從其它組件中以Intent 的形式產生的一個請求;

  B、Activities 可以在任何時候被一個具有相同IntentFilter 的新的Activity 取代。

  AndroidManifest文件中含有如下過濾器的Activity組件為默認啟動類當程序啟動時系統自動調用它

 

 intent-filter> 
       <action android:name="android.intent.action.MAIN" /> 
       <category android:name="android.intent.category.LAUNCHER" /> 
</intent-filter> 

<intent-filter>
       <action android:name="android.intent.action.MAIN" />
       <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
  Activity的註冊



  AndroidManifest文件中進行註冊格式如下:

  <activity>元素的name 屬性指定瞭實現瞭這個activity 的Activity 的子類。icon 和label 屬性指向瞭包含展示給用戶的此activity 的圖標和標簽的資源文件。

 

  Activity的激活

  Activity的激活通過傳遞一個Intent 對象至Context.startActivity()或Activity.startActivityForResult()以載入(或指定新工作給)一個activity。相應的activity 可以通過調用getIntent() 方法來查看激活它的intent。如果它期望它所啟動的那個activity 返回一個結果,它會以調用startActivityForResult()來取代startActivity()。比如說,如果它啟動瞭另外一個Activity 以使用戶挑選一張照片,它也許想知道哪張照片被選中瞭。結果將會被封裝在一個Intent 對象中,並傳遞給發出調用的activity 的onActivityResult() 方法。

 

  Activity關閉

  可以通過調用它的finish()方法來關閉一個activity

 

  Activity的生命周期

  與Activity生命周期相關的就是任務。任務其實就是Activity 的棧它由一個或多個Activity組成的共同完成一個完整的用戶體驗, 換句話說任務就是” 應用程序” (可以是一個也可以是多個,比如你想讓用戶看到某個地方的街道地圖。而已經存在一個具有此功能的activity 瞭,那麼你的activity 所需要做的工作就是把請求信息放到一個Intent 對象裡面,並把它傳遞給startActivity()。於是屏幕就會顯示那個地圖。而當用戶按下BACK 鍵的時候,上一個Activity 又會再一次的顯示在屏幕上,此時任務是由應用程序中兩個的相關Activity組成的)棧底是啟動整個任務的Activity,棧頂的是當前運行的用戶可以交互的Activity,當一個Activity 啟動另外一個的時候,新的activity 就被壓入棧,並成為當前運行的Activity。而前一個Activity 仍保持在棧之中。當用戶按下BACK 鍵的時候,當前Activity 出棧,而前一個恢復為當前運行的Activity。棧中保存的其實是對象,棧中的Activity 永遠不會重排,隻會壓入或彈出,所以如果發生瞭諸如需要多個街道地圖顯示的情況,就會使得一個任務中出現多個同一Activity 子類的實例同時存在。

  任務中的所有Activity 是作為一個整體進行移動的。整個的任務(即activity 棧)可以移到前臺,或退至後臺。舉個例子說,比如當前任務在棧中存有四個Activity──三個在當前Activity 之下。當用戶按下HOME 鍵的時候,回到瞭應用程序加載器,然後選擇瞭一個新的應用程序(也就是一個新任務)。則當前任務遁入後臺,而新任務的根Activity 顯示出來。然後,過瞭一小會兒,用戶再次回到瞭應用程序加載器而又選擇瞭前一個應用程序(上一個任務)。於是那個任務,帶著它棧中所有的四個Activity,再一次的到瞭前臺。當用戶按下BACK 鍵的時候,屏幕不會顯示出用戶剛才離開的Activity(上一個任務的根Activity)。取而代之,當前任務的棧中最上面的Activity 被彈出,而同一任務中的上一個Activity 顯示瞭出來。

  Android系統是一個多任務(Multi-Task)的操作系統,可以在用手機聽音樂的同時,也執行其他多個程序。每多執行一個應用程序,就會多耗費一些系統內存,當同時執行的程序過多,或是關閉的程序沒有正確釋放掉內存,系統就會覺得越來越慢,甚至不穩定。

  為瞭解決這個問題, Android 引入瞭一個新的機制– 生命周期(Life Cycle)。

  Android 應用程序的生命周期是由Android 框架進行管理,而不是由應用程序直接控制。通常,每一個應用程序(入口一般會是一個Activity 的onCreate 方法),都會產生一個進程(Process)。當系統內存即將不足的時候,會依照優先級自動進行進程(process)的回收。不管是使用者或開發者, 都無法確定的應用程序何時會被回收。所以為瞭很好的防止數據丟失和其他問題,瞭解生命周期很重要。

  Activity生命周期:

 
 

  Activity整個生命周期的4種狀態、7個重要方法和3個嵌套循環

  4種狀態:

    1、活動(Active/Running)狀態

    當Activity運行在屏幕前臺(處於當前任務活動棧的最上面),此時它獲取瞭焦點能響應用戶的操作,屬於運行狀態,同一個時刻隻會有一個Activity 處於活動(Active)或運行(Running)狀態

    2、暫停(Paused)狀態

    當Activity失去焦點但仍對用戶可見(如在它之上有另一個透明的Activity或Toast、AlertDialog等彈出窗口時)它處於暫停狀態。暫停的Activity仍然是存活狀態(它保留著所有的狀態和成員信息並保持和窗口管理器的連接),但是當系統內存極小時可以被系統殺掉

    3、停止(Stopped)狀態

    完全被另一個Activity遮擋時處於停止狀態,它仍然保留著所有的狀態和成員信息。隻是對用戶不可見,當其他地方需要內存時它往往被系統殺掉

    4、非活動(Dead)狀態

    Activity 尚未被啟動、已經被手動終止,或已經被系統回收時處於非活動的狀態,要手動終止Activity,可以在程序中調用"finish"方法。

 

  7個重要方法

  當Activity從一種狀態進入另一狀態時系統會自動調用下面相應的方法來通知用戶這種變化當Activity第一次被實例化的時候系統會調用,整個生命周期隻調用1次這個方法

  通常用於初始化設置: 1、為Activity設置所要使用的佈局文件 2、為按鈕綁定監聽器等靜態的設置操作,使用方法onCreate(Bundle savedInstanceState);

  當Activity可見未獲得用戶焦點不能交互時系統會調用onStart();

  當Activity已經停止然後重新被啟動時系統會調用onRestart();

  當Activity可見且獲得用戶焦點能交互時系統會調用onResume();

  當系統啟動另外一個新的Activity時,在新Activity啟動之前被系統調用保存現有的Activity中的持久數據、停止動畫等,這個實現方法必須非常快。當系統而不是用戶自己出於回收內存時,關閉瞭Activity 之後。用戶會期望當他再次回到這個activity 的時候,它仍保持著上次離開時的樣子。此時用到瞭onSaveInstanceState(),方法onSaveInstanceState()用來保存Activity被殺之前的狀態,在onPause()之前被觸發,當系統為瞭節省內存銷毀瞭Activity(用戶本不想銷毀)時就需要重寫這個方法瞭,當此Activity再次被實例化時會通過onCreate(Bundle savedInstanceState)將已經保存的臨時狀態數據傳入因為onSaveInstanceState()方法不總是被調用,觸發條件為(按下HOME鍵,按下電源按鍵關閉屏幕,橫豎屏切換情況下),你應該僅重寫onSaveInstanceState()來記錄Activity的臨時狀態,而不是持久的數據。應該使用onPause()來存儲持久數據。

  當Activity被新的Activity完全覆蓋不可見時被系統調用onStop();

  當Activity(用戶調用finish()或系統由於內存不足)被系統銷毀殺掉時系統調用onDestroy(),(整個生命周期隻調用1次)用來釋放onCreate ()方法中創建的資源,如結束線程等。

 

  3個嵌套循環

    1、Activity完整的生命周期:從第一次調用onCreate()開始直到調用onDestroy()結束

    2、Activity的可視生命周期:從調用onStart()到相應的調用onStop()

    在這兩個方法之間,可以保持顯示Activity所需要的資源。如在onStart()中註冊一個廣播接收者監聽影響你的UI的改變,在onStop() 中註銷。

    3、Activity的前臺生命周期:從調用onResume()到相應的調用onPause()。

 

  舉例子:

  有3個Acitivity,分別用One,Two(透明的),Three表示,One是應用啟動時的主Activity

  啟動第一個界面Activity One時,它的次序是

  onCreate (ONE) – onStart (ONE) – onResume(ONE)

  點"打開透明Activity"按鈕時,這時走的次序是

  onPause(ONE) – onCreate(TWO) – onStart(TWO) – onResume(TWO)

  再點back回到第一個界面,Two會被殺這時走的次序是

  onPause(TWO) – onActivityResult(ONE) – onResume(ONE) – onStop(TWO) – onDestroy(TWO)

  點"打開全屏Activity"按鈕時,這時走的次序是

  onPause(ONE) – onCreate(Three) – onStart(Three) – onResume(Three) – onStop(ONE)

  再點back回到第一個界面,Three會被殺這時走的次序是

  onPause(Three) – onActivityResult(ONE) – onRestart(ONE) – onStart(ONE)- onResume(ONE) – onStop(Three) – onDestroy(Three)

  <補充>如果按HOME將程序掛到後臺,次序是

  onSaveInstanceState()-onPause(ONE)-onStop(ONE)

  <補充>從後臺返回,次序是

  onRestart(ONE)-onStart(ONE) – onResume(ONE)

  再點back退出應用時,它的次序是

  onPause(ONE) – onStop(ONE) – onDestroy(ONE)

 

 

 

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *