前些天看了一個要上大四的學長寫的一篇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)