1. 程式人生 > >Android面試--四大元件

Android面試--四大元件

Android四大元件分別為activity、service、content provider、broadcast receiver。

一、android四大元件詳解

1、Activity

(1)一個Activity通常就是一個單獨的螢幕(視窗),它上面可以顯示一些控制元件也可以監聽並處理使用者的事件做出響應。

(2)Activity之間通過Intent進行通訊。

(3)android應用中每一個Activity都必須要在AndroidManifest.xml配置檔案中宣告,否則系統將不識別也不執行該Activity。

2、Service

(1)service用於在後臺完成使用者指定的操作。service分為兩種:
(a)started(啟動):當應用程式元件(如activity)呼叫startService()方法啟動服務時,服務處於started狀態。
(b)bound(繫結):當應用程式元件呼叫bindService()方法繫結到服務時,服務處於bound狀態。

(2)startService()與bindService()區別:
(a)started service(啟動服務)是由其他元件呼叫startService()方法啟動的,
這導致服務的onStartCommand()方法被呼叫。當服務是started狀態時,
其生命週期與啟動它的元件無關,並且可以在後臺無限期執行,即使啟動服務的元件已經被銷燬。
因此,服務需要在完成任務後呼叫stopSelf()方法停止,或者由其他元件呼叫stopService()方法停止。

(b)使用bindService()方法啟用服務,呼叫者與服務繫結在了一起,
呼叫者一旦退出,服務也就終止,大有“不求同時生,必須同時死”的特點。

(3)開發人員需要在應用程式配置檔案中宣告全部的service,使用標籤。

(4)Service通常位於後臺執行,它一般不需要與使用者互動,因此Service元件沒有圖形使用者介面。
Service元件需要繼承Service基類。Service元件通常用於為其他元件提供後臺服務或監控其他元件的執行狀態。

3、Content Psrovider

(1)android平臺提供了Content Provider使一個應用程式的指定資料集提供給其他應用程式。
其他應用可以通過ContentResolver類從該內容提供者中獲取或存入資料。

(2)只有需要在多個應用程式間共享資料是才需要內容提供者。
例如,通訊錄資料被多個應用程式使用,且必須儲存在一個內容提供者中。它的好處是統一資料訪問方式。
(3)ContentProvider實現資料共享。ContentProvider用於儲存和獲取資料,並使其對所有應用程式可見。
這是不同應用程式間共享資料的唯一方式,因為android沒有提供所有應用共同訪問的公共儲存區。

(4)開發人員不會直接使用ContentProvider類的物件,大多數是通過ContentResolver物件實現對ContentProvider的操作。

(5)ContentProvider使用URI來唯一標識其資料集,這裡的URI以content://作為字首,表示該資料由ContentProvider來管理。

4、Broadcast Receiver

(1)你的應用可以使用它對外部事件進行過濾,只對感興趣的外部事件(如當電話呼入時,或者資料網路可用時)
進行接收並做出響應。廣播接收器沒有使用者介面。
然而,它們可以啟動一個activity或serice來響應它們收到的資訊,或者用NotificationManager來通知使用者。
通知可以用很多種方式來吸引使用者的注意力,例如閃動背燈、震動、播放聲音等。
一般來說是在狀態列上放一個持久的圖示,使用者可以開啟它並獲取訊息。

(2)廣播接收者的註冊有兩種方法,分別是程式動態註冊和AndroidManifest檔案中進行靜態註冊。

(3)動態註冊廣播接收器特點是當用來註冊的Activity關掉後,廣播也就失效了。
靜態註冊無需擔憂廣播接收器是否被關閉,只要裝置是開啟狀態,廣播接收器也是開啟著的。
也就是說哪怕app本身未啟動,該app訂閱的廣播在觸發時也會對它起作用。

二、android四大元件總結:

(1)4大元件的註冊

4大基本元件都需要註冊才能使用,每個Activity、service、Content Provider都需要在AndroidManifest檔案中進行配置。
AndroidManifest檔案中未進行宣告的activity、服務以及內容提供者將不為系統所見,從而也就不可用。
而broadcast receiver廣播接收者的註冊分靜態註冊(在AndroidManifest檔案中進行配置)
和通過程式碼動態建立並以呼叫Context.registerReceiver()的方式註冊至系統。
需要注意的是在AndroidManifest檔案中進行配置的廣播接收者會隨系統的啟動而一直處於活躍狀態,
只要接收到感興趣的廣播就會觸發(即使程式未執行)。

(2)4大元件的啟用

內容提供者的啟用:當接收到ContentResolver發出的請求後,內容提供者被啟用。
而其它三種元件activity、服務和廣播接收器被一種叫做intent的非同步訊息所啟用。

(3)4大元件的關閉

內容提供者僅在響應ContentResolver提出請求的時候啟用。而一個廣播接收器僅在響應廣播資訊的時候啟用。
所以,沒有必要去顯式的關閉這些元件。
Activity關閉:可以通過呼叫它的finish()方法來關閉一個activity。
服務關閉:對於通過startService()方法啟動的服務要呼叫Context.stopService()方法關閉服務,
使用bindService()方法啟動的服務要呼叫Context.unbindService()方法關閉服務。

(4)android中的任務(activity棧)

(a)任務其實就是activity的棧,它由一個或多個Activity組成,
共同完成一個完整的使用者體驗。棧底的是啟動整個任務的Activity,
棧頂的是當前執行的使用者可以互動的Activity,當一個activity啟動另外一個的時候,
新的activity就被壓入棧,併成為當前執行的activity。而前一個activity仍保持在棧之中。
當用戶按下BACK鍵的時候,當前activity出棧,而前一個恢復為當前執行的activity。
棧中儲存的其實是物件,棧中的Activity永遠不會重排,只會壓入或彈出。

(b)任務中的所有activity是作為一個整體進行移動的。
整個的任務(即activity棧)可以移到前臺,或退至後臺。

(c)Android系統是一個多工(Multi-Task)的作業系統,可以在用手機聽音樂的同時,
也執行其他多個程式。每多執行一個應用程式,就會多耗費一些系統記憶體,
當同時執行的程式過多,或是關閉的程式沒有正確釋放掉記憶體,系統就會覺得越來越慢,
甚至不穩定。為了解決這個問題,Android引入了一個新的機制,即生命週期(Life Cycle)。

<—————-關於Activity的知識點—————–>
二、Activity的生命週期:

1.七大生命週期:
onCreate() 第一次建立時執行;
onStart() 顯示視窗時執行;
onResume() 可獲取使用者焦點時執行;
onPause() 失去使用者焦點時執行;
onStop() 關閉視窗時執行;
onRestart() 重新顯示視窗時執行;
onDestroy() 銷燬時執行;

2.各種情況下生命週期的回撥規律:

(1)應用程式進來主頁面後:
onCreate() 建立activity時
onStart () 啟動時
onResume() 顯示時

(2) 按返回退出後:

onPause()    暫停時  -->喪失使用者焦點的第一個特徵
onStop()     停止時
onDestroy()  銷燬時

(3)按home後:

onPause()    暫停時   
onStop()     停止時

(4)在home頁再次點選這個應用:

onRestart()   
onStart()    啟動時
onResume ()  顯示時

(5)切換成橫屏後:

onPause()    暫停時          
onStop()     停止時
onDestroy()  銷燬時
onCreate()   建立activity時
onStart()   啟動時
onResume()  顯示時  

(注意)設定 Activity 的 android:configChanges=”orientation|keyboardHidden|screenSize”時,
切屏不會重新呼叫各個生命週期,只會執行 onConfigurationChanged 方法

三、Activity的啟動模式:

第一:什麼是啟動模式,啟動的模式,理解成一個activity的啟動的方式。
分為四種:

1、首先,我們現在沒有指定任何啟動模式,叫預設模式(standard)
標準的啟動模式,每次啟用activity時都會建立activity,建立之後,會把它放到任務棧裡。

2、singleTop
如果在任務的棧頂,就重用該例項,如果棧頂不是這個activity,就重新例項化一個activity放到棧頂。

3、singleTask
如果在棧中已經有該activity的例項,就重複使用該例項,並且把壓在它上邊的例項全都清除掉;
如果在棧中沒有找到該activity的例項,就建立一個放在棧頂。

4、singleInstance
與singletask的區別是,存放singleinstance模式的activity的回退棧,
不能有其他任何activity物件,也就是說,它自己單獨有一個回退棧。

*)我們可以在 AndroidManifest.xml 配置的 android:launchMode 屬性為以上四種之一即可

第二:兩個 Activity 之間跳轉時必然會執行的是哪幾個方法?(重要)

一般情況下比如說有兩個 activity,分別叫 A,B。當在 A 裡面啟用 B 元件的時候,A 會呼叫 onPause()方法,然後 B 呼叫 onCreate() ,onStart(), onResume()。這個時候 B 覆蓋了窗體, A 會呼叫 onStop()方法. 如果 B 是個透明的,或者是對話方塊的樣式, 就不會呼叫 A 的onStop()方法

第三:如何將一個 Activity 設定成視窗的樣式?

只需要給我們的 Activity 配置如下屬性即可。
android:theme=”@android:style/Theme.Dialog

第四:如何退出 Activity?如何安全退出已呼叫多個 Activity 的 Application?

1、通常情況使用者退出一個 Activity 只需按返回鍵,我們寫程式碼想退出 activity 直接呼叫 finish()方法就行。

2、記錄開啟的 Activity:
每開啟一個 Activity,就記錄下來。在需要退出時,關閉每一個 Activity 即可。
//虛擬碼
List lists ;// 在 application 全域性的變數裡面
lists = new ArrayList();
lists.add(this);
for(Activity activity: lists)
{
activity.finish();
}
lists.remove(this);

3、傳送特定廣播:
在需要結束應用時,傳送一個特定的廣播,每個 Activity 收到廣播後,關閉即可。
//給某個 activity 註冊接受接受廣播的意圖
registerReceiver(receiver, filter)
//如果過接受到的是 關閉 activity 的廣播 就呼叫 finish()方法 把當前的 activity finish()掉

4、遞迴退出
在開啟新的 Activity 時使用 startActivityForResult,然後自己加標誌,在 onActivityResult 中處理,遞迴關閉。

5、其實 也可以通過 intent 的 flag 來實現 intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) 啟用
一個新的 activity。此時如果該任務棧中已經有該 Activity,那麼系統會把這個 Activity 上面的所有 Activity 幹掉。其
實相當於給 Activity 配置的啟動模式為 SingleTop。

<——————Service的知識點—————————>

第一:Service 是否在 main thread 中執行, service 裡面是否能執行耗時的操作?

預設情況,如果沒有顯示的指 service 所執行的程序, Service 和 activity 是
執行在當前 app 所在程序的 mainthread(UI 主執行緒)裡面。
service 裡面不能執行耗時的操作(網路請求,拷貝資料庫,大檔案 )
特殊情況 ,可以在清單檔案配置 service 執行所在的程序 ,讓 service 在另外的程序中執行。

第二:請描述一下 Service 的生命週期

Service 有繫結模式和非繫結模式,以及這兩種模式的混合使用方式。不同的使用方法生命週期方法也不同。
非繫結模式:當第一次呼叫 startService 的時候執行的方法依次為 onCreate()、onStartCommand(), (onStart())
當 Service 關閉的時候呼叫 onDestory 方法。
繫結模式:第一次 bindService()的時候,執行的方法為 onCreate()、onBind()解除繫結的時候會執行
onUnbind()、onDestory()。

上面的兩種生命週期是在相對單純的模式下的情形。我們在開發的過程中還必須注意 Service 例項只會有一個,
也就是說如果當前要啟動的 Service 已經存在了那麼就不會再次建立該 Service 當然也不會呼叫 onCreate()方法。

一個 Service 可以被多個客戶進行繫結,只有所有的繫結物件都執行了 onBind()方法後該 Service 才會銷燬,
不過如果有一個客戶執行了 onStart()方法,那麼這個時候如果所有的 bind 客戶都執行了 unBind()該 Service 也不會銷燬。

第三:Service 的 onStartCommand 方法有幾種返回值?各代表什麼意思?

有四種返回值,不同值代表的意思如下:
(1)START_STICKY:如果 service 程序被 kill 掉,保留 service 的狀態為開始狀態,但不保留遞送的 intent 物件。
隨後 系 統 會 嘗 試 重 新 創 建 service , 由 於 服 務 狀 態 為 開 始 狀 態 ,
所以建立服務後一定會呼叫onStartCommand(Intent,int,int)方法。如果在此期間沒有任何啟動命令被傳遞到 service,
那麼引數 Intent 將為 null。

(2)START_NOT_STICKY:“非粘性的”。使用這個返回值時,如果在執行完 onStartCommand 後,服務被異常 kill
掉,系統不會自動重啟該服務。

(3)START_REDELIVER_INTENT:重傳 Intent。使用這個返回值時,如果在執行完 onStartCommand 後,服務被異
常 kill 掉,系統會自動重啟該服務,並將 Intent 的值傳入。

(4)START_STICKY_COMPATIBILITY:START_STICKY 的相容版本,但不保證服務被 kill 後一定能重啟

第四:Service 的 onRebind(Intent)方法在什麼情況下會執行?

如果在 onUnbind()方法返回 true 的情況下會執行,否則不執行。

<—————— BroadCastReceiver—————————->

第一:簡單介紹:
BroadCastReceiver 是 Android 四大元件之一,主要用於接收系統或者 app 傳送的廣播事件。

廣播分兩種:有序廣播和無序廣播。
內部通訊實現機制:通過 Android 系統的 Binder 機制實現通訊。

無序廣播:完全非同步,邏輯上可以被任何廣播接收者接收到。優點是效率較高。缺點是一個接收者不能將處理結果傳遞給下一個接收者,並無法終止廣播 intent 的傳播。

有序廣播:按照被接收者的優先順序順序,在被接收者中依次傳播。比如有三個廣播接收者 A,B,C,優先順序是 A >
B > C。那這個訊息先傳給 A,再傳給 B,最後傳給 C。每個接收者有權終止廣播,比如 B 終止廣播,C 就無法接收到。
此外 A 接收到廣播後可以對結果物件進行操作,當廣播傳給 B 時,B 可以從結果物件中取得 A 存入的資料。
在通過 Context.sendOrderedBroadcast(intent, receiverPermission, resultReceiver, scheduler, initialCode,
initialData, initialExtras)時我們可以指定 resultReceiver 廣播接收者,這個接收者我們可以認為是最終接收者,
通常情況下如果比他優先順序更高的接收者如果沒有終止廣播,那麼他的 onReceive 會被執行兩次,
第一次是正常的按照優先順序順序執行,第二次是作為最終接收者接收。如果比他優先順序高的接收者終止了廣播,
那麼他依然能接收到廣播。
在我們的專案中經常使用廣播接收者接收系統通知,比如開機啟動、sd 掛載、低電量、外撥電話、鎖屏等。
如果我們做的是播放器,那麼監聽到使用者鎖屏後我們應該將我們的播放之暫停等。

第二:BroadCastReceiver 的生命週期:

a. 廣播接收者的生命週期非常短暫的,在接收到廣播的時候建立,onReceive()方法結束之後銷燬;
b. 廣播接收者中不要做一些耗時的工作,否則會彈出 Application No Response 錯誤對話方塊;
c. 最好也不要在廣播接收者中建立子執行緒做耗時的工作,因為廣播接收者被銷燬後進程就成為了空程序,很容易
被系統殺掉;
d. 耗時的較長的工作最好放在服務中完成;

第三:什麼是最終廣播接收者?

最終廣播是我們自己應用傳送有序廣播時通過 ContextWrapper.sendOrderedBroadcast()方法指定的當前應用下的廣播,該廣播可能會被執行兩次,第一次是作為普通廣播按照優先順序接收廣播,
第二次是作為 final receiver 必須接收一次。

第四:廣播的優先順序對無序廣播生效嗎?—- 生效!!!!

第五:動態註冊的廣播誰的優先順序高?—– 誰先註冊誰的優先順序高!!

第六:如何判斷當前 BroadcastReceiver 接收到的是有序廣播還是無序廣播 ?

在 BroadcastReceiver 類中 onReceive()方法中,可以呼叫 boolean b = isOrderedBroadcast();
該方法是BroadcastReceiver 類中提供的方法,用於告訴我們當前的接收到的廣播是否為有序廣播

<——————ContentProvider& 資料庫——–>

第一:請介紹下 ContentProvider 是如何實現資料共享的?

在 Android 中如果想將自己應用的資料(一般多為資料庫中的資料)提供給第三發應用,那麼我們只能通過
ContentProvider 來實現了。
ContentProvider 是應用程式之間共享資料的介面。使用的時候首先自定義一個類繼承 ContentProvider,然後
覆寫 query、insert、update、delete 等方法。因為其是四大元件之一因此必須在 AndroidManifest 檔案中進行註冊。

第二:為什麼要用 ContentProvider?它和 sql 的實現上有什麼差別?

ContentProvider 遮蔽了資料儲存的細節,內部實現對使用者完全透明,使用者只需要關心操作資料的 uri 就可以了,
ContentProvider 可以實現不同 app 之間共享。
Sql 也有增刪改查的方法,但是 sql 只能查詢本應用下的資料庫。而 ContentProvider 還可以去增刪改查本
地檔案. xml 檔案的讀取等。

第三:說說 ContentProvider、ContentResolver、ContentObserver 之間的關係
ContentProvider 內容提供者,用於對外提供資料
ContentResolver.notifyChange(uri)發出訊息
ContentResolver 內容解析者,用於獲取內容提供者提供的資料
ContentObserver 內容監聽器,可以監聽資料的改變狀態
ContentResolver.registerContentObserver()監聽訊息。