android四大組件的運行狀態(tài)

android四大組件:Activity,Service,BroadcastReceiver和ContentProvider.

一、異同點

android的四大組件組件中,除了BroadcastReceiver以外,其他的三種都必須在Android-Manifest中注冊,對于BroadcastReceiver來說,他可以在Android-Manifest中注冊,也可以通過代碼來注冊。在調(diào)用方式上,Activity,Service,和、BroadcastReceiver需要借助Intent,而ContentProvider不需要。

二、Activity的相關介紹

Activity是一種展示組件,用于向用戶直接的展示一個界面,并且可以接收用戶輸入的信息來進行交互。

1、什么是Activity?

Activity是一個負責與用戶交互的組件,Activity中所有操作都與用戶密切相關,可以通過setContentView(View)來顯示指定控件。

在一個android應用中,一個Activity通常就是一個單獨的屏幕,它上面可以顯示一些控件也可以監(jiān)聽并處理用戶的事件做出響應。

2、請描述一下Activity生命周期。

onCreate(Bundle savedInstanceState):

創(chuàng)建activity時調(diào)用。設置在該方法中,還以Bundle的形式提供對以前儲存的任何狀態(tài)的訪問!

onStart():

activity變?yōu)樵谄聊簧蠈τ脩艨梢姇r調(diào)用。

onResume():

activity開始與用戶交互時調(diào)用(無論是啟動還是重新啟動一個活動,該方法

總是被調(diào)用的)。

onPause():

activity被暫?;蚴栈豤pu和其他資源時調(diào)用,該方法用于保存活動狀態(tài)的,也

是保護現(xiàn)場,壓棧吧!

onStop():

activity被停止并轉為不可見階段及后續(xù)的生命周期事件時調(diào)用。

onRestart():

重新啟動activity時調(diào)用。該活動仍在棧中,而不是啟動新的活動。

onDestroy():

activity被完全從系統(tǒng)內(nèi)存中移除時調(diào)用,該方法被調(diào)用

3、如何退出Activity?如何安全退出已調(diào)用多個Activity的Application?

在Android中退出程序比較麻煩,尤其是在多個Activity的程序中,在2.2之前可以采用如下代碼退出程序:

1.?ActivityManager am = (ActivityManager)getSystemService (Context.ACTIVITY_SERVICE);

2.?am.restartPackage(getPackageName());

此種方法是一種最方便和最簡單的退出程序的辦法,但是在2.2和2.2之后就不能用了,一種常用的方法是自定義一個Activity的棧,在程序退出時將棧中的所有的Activity進行finish。

還有一些其他的方式,在這http://alex-yang-xiansoftware-com.iteye.com/blog/1099207可查看。

4、如果后臺的Activity由于某原因被系統(tǒng)回收了,如何在被系統(tǒng)回收之前保存當前狀態(tài)?

答:重寫onSaveInstanceState()方法,在此方法中保存需要保存的數(shù)據(jù),該方法將會在activity被回收之前調(diào)用。通過重寫onRestoreInstanceState()方法可以從中提取保存好的數(shù)據(jù)

5、?activity在屏幕旋轉時的生命周期

答:不設置Activity的android:configChanges時,切屏會重新調(diào)用各個生命周期,切橫屏時會執(zhí)行一次,切豎屏時會執(zhí)行兩次;設置Activity的android:configChanges="orientation"時,切屏還是會重新調(diào)用各個生命周期,切橫、豎屏時只會執(zhí)行一次;設置Activity的android:configChanges="orientation|keyboardHidden"時,切屏不會重新調(diào)用各個生命周期,只會執(zhí)行onConfigurationChanged方法。

6、?activity的啟動模式有哪些?是什么含義?

答:在android里,有4種activity的啟動模式,分別為:

“standard” (默認)

“singleTop”

“singleTask”

“singleInstance”

當應用運行起來后就會開啟一條線程,線程中會運行一個任務棧,當Activity實例創(chuàng)建后就會放入任務棧中。Activity啟動模式的設置在AndroidManifest.xml文件中,通過配置Activity的屬性android:launchMode=""設置。

1. Standared模式(默認)

我們平時直接創(chuàng)建的Activity都是這種模式的Activity,這種模式的Activity的特點是:只要你創(chuàng)建了Activity實例,一旦激活該Activity,則會向任務棧中加入新創(chuàng)建的實例,退出Activity則會在任務棧中銷毀該實例。

2. SingleTop模式

這種模式會考慮當前要激活的Activity實例在任務棧中是否正處于棧頂,如果處于棧頂則無需重新創(chuàng)建新的實例,會重用已存在的實例,否則會在任務棧中創(chuàng)建新的實例。

3. SingleTask模式

如果任務棧中存在該模式的Activity實例,則把棧中該實例以上的Activity實例全部移除,調(diào)用該實例的newInstance()方法重用該Activity,使該實例處於棧頂位置,否則就重新創(chuàng)建一個新的Activity實例。

4. SingleInstance模式

當該模式Activity實例在任務棧中創(chuàng)建后,只要該實例還在任務棧中,即只要激活的是該類型的Activity,都會通過調(diào)用實例的newInstance()方法重用該Activity,此時使用的都是同一個Activity實例,它都會處于任務棧的棧頂。此模式一般用于加載較慢的,比較耗性能且不需要每次都重新創(chuàng)建的Activity。

7、跟activity和Task 有關的 Intent啟動方式有哪些?其含義?核心的Intent Flag有:

FLAG_ACTIVITY_NEW_TASK

FLAG_ACTIVITY_CLEAR_TOP

FLAG_ACTIVITY_SINGLE_TOP

FLAG_ACTIVITY_RESET_TASK_IF_NEEDED

FLAG_ACTIVITY_NEW_TASK

如果設置,這個Activity會成為歷史stack中一個新Task的開始。一個Task(從啟動它的Activity到下一個Task中的Activity)定義了用戶可以遷移的Activity原子組。Task可以移動到前臺和后臺;在某個特定Task中的所有Activity總是保持相同的次序。這個標志一般用于呈現(xiàn)“啟動”類型的行為:它們提供用戶一系列可以單獨完成的事情,與啟動它們的Activity完全無關。

FLAG_ACTIVITY_CLEAR_TOP

如果設置,并且這個Activity已經(jīng)在當前的Task中運行,因此,不再是重新啟動一個這個Activity的實例,而是在這個Activity上方的所有Activity都將關閉,然后這個Intent會作為一個新的Intent投遞到老的Activity(現(xiàn)在位于頂端)中。

FLAG_ACTIVITY_SINGLE_TOP

如果設置,并且這個Activity已經(jīng)在當前的Task中運行,因此,不再是重新啟動一個這個Activity的實例,而是在這個Activity上方的所有Activity都將關閉,然后這個Intent會作為一個新的Intent投遞到老的Activity(現(xiàn)在位于頂端)中。

FLAG_ACTIVITY_RESET_TASK_IF_NEEDED

如果設置這個標志,這個activity不管是從一個新的棧啟動還是從已有棧推到棧頂,它都將以the front door of the task的方式啟動。這就講導致任何與應用相關的棧都講重置到正常狀態(tài)(不管是正在講activity移入還是移除),如果需要,或者直接重置該棧為初始狀態(tài)。

三、Service

Service是一種計算型組件,用于在后臺執(zhí)行一系列的計算任務。由于在后臺,所以用戶無法直接感知到他的存在。Service和activity組件略有不同,activity組件只有一種運行模式,即activity處于啟動狀態(tài),而Service卻有兩種狀態(tài):啟動和綁定狀態(tài)。

1、android 關于service生命周期的onCreate()和onStart()說法正確的是(ad)(多選題)

A、當?shù)谝淮螁拥臅r候先后調(diào)用onCreate()和onStart()方法

B、當?shù)谝淮螁拥臅r候只會調(diào)用onCreate()方法

C、如果service已經(jīng)啟動,將先后調(diào)用onCreate()和onStart()方法

D、如果service已經(jīng)啟動,只會執(zhí)行onStart()方法,不在執(zhí)行onCreate()方法

2、Service是如何啟動

A. 通過startService;Service會經(jīng)歷onCreate->onStart;stopService的時候直接onDestroy;如果是調(diào)用者(TestServiceHolder)自己直接退出而沒有調(diào)用stopService的話,Service會一直在后臺運行,下次TestServiceHolder再起來可以stopService。

B. 通過bindService;Service只會運行onCreate,這個時候TestServiceHolder和TestService綁定在一起,TestServiceHolder退出了,Srevice就會調(diào)onUnbind->onDestroyed,所謂綁定在一起就共存亡了。

3、Service用在哪個線程

默認情況下Service是運行在啟動該Service的應用主線程的,如果Service中的操作占用大量的CPU資源或有阻斷操作(比如播放MP3或者訪問網(wǎng)絡)會影響應用主線程的響應性能,甚至會造成“應用程序無響應(ANR)”問題。

4、簡單介紹服務

服務是沒有界面的長生命周期的代碼。一個很好的例子是媒體播放器從列表中播放歌曲。在一個媒體播放器程序中,大概要有一個或多個活動(activity)來供用戶選擇歌曲并播放它。然而,音樂的回放就不能使用活動(activity)了,因為用戶希望他導航到其他界面時音樂繼續(xù)播放。這種情況下,媒體播放器活動(activity)要用Context.startService()啟動一個服務來在后臺運行保持音樂的播放。系統(tǒng)將保持這個音樂回放服務的運行直到它結束。注意一下,你要用Context.bindService()方法連接服務(如果它沒有運行,要先啟動它)。當連接到服務后,你可以通過服務暴露的一個接口和它通信。對于音樂服務,它允許你暫停、倒帶,等等。

5、service和Thread區(qū)別?

1).Thread:Thread 是程序執(zhí)行的最小單元,它是分配CPU的基本單位??梢杂?Thread 來執(zhí)行一些異步的操作。

2).Service:Service 是android的一種機制,當它運行的時候如果是Local Service,那么對應的 Service 是運行在主進程的 main 線程上的。如:onCreate,onStart 這些函數(shù)在被系統(tǒng)調(diào)用的時候都是在主進程的 main 線程上運行的。如果是Remote Service,那么對應的 Service 則是運行在獨立進程的 main 線程上。

四、BroadcastReceiver

BroadcastReceiver是一種消息型組件,用于在不同的組件中和不同的應用之間傳遞消息。同樣無法被用戶指甲感知到,因為他工作在系統(tǒng)內(nèi)部。

在Android中,Broadcast是一種廣泛運用的在應用程序之間傳輸信息的機制。

1、用途:

實現(xiàn)了不同的程序之間的數(shù)據(jù)傳輸與共享,因為只要是和發(fā)送廣播的action相同的接受者都能接受這個廣播。典型的應用就是android自帶的短信,電話等等廣播,只要我們實現(xiàn)了他們的action的廣播,那么我們就能接收他們的數(shù)據(jù)了,以便做出一些處理。比如說攔截系統(tǒng)短信,攔截騷擾電話等

起到了一個通知的作用,比如在service中要通知主程序,更新主程序的UI等

因為service是沒有界面的,所以不能直接獲得主程序中的控件,這樣我們就只能在主程序中實現(xiàn)一個廣播接受者專門用來接受service發(fā)過來的數(shù)據(jù)和通知了

2、使用場景:

同一app內(nèi)部的同一組件內(nèi)的消息通信(單個或多個線程之間);

同一app內(nèi)部的不同組件之間的消息通信(單個進程);

同一app具有多個進程的不同組件之間的消息通信;

不同app之間的組件之間消息通信;

Android系統(tǒng)在特定情況下與App之間的消息通信。

3、實現(xiàn)原理:

從實現(xiàn)原理看上,Android中的廣播使用了觀察者模式,基于消息的發(fā)布/訂閱事件模型。因此,從實現(xiàn)的角度來看,Android中的廣播將廣播的發(fā)送者和接受者極大程度上解耦,使得系統(tǒng)能夠方便集成,更易擴展。具體實現(xiàn)流程要點粗略概括如下:

廣播接收者BroadcastReceiver通過Binder機制向AMS(Activity Manager Service)進行注冊;

廣播發(fā)送者通過binder機制向AMS發(fā)送廣播;

AMS查找符合相應條件(IntentFilter/Permission等)的BroadcastReceiver,將廣播發(fā)送到BroadcastReceiver(一般情況下是Activity)相應的消息循環(huán)隊列中;

消息循環(huán)執(zhí)行拿到此廣播,回調(diào)BroadcastReceiver中的onReceive()方法。

4、注冊方式

有倆種注冊方式分別是靜態(tài)注冊和動態(tài)注冊

靜態(tài)注冊

在AndroidManifest.xml 中:? ? . . .android:exported —— 此broadcastReceiver能否接收其他App的發(fā)出的廣播(其默認值是由receiver中有無intent-filter決定的,如果有intent-filter,默認值為true,否則為false。)android:name? —— 此broadcastReceiver類名;android:permission? ——如果設置,具有相應權限的廣播發(fā)送方發(fā)送的廣播才能被此broadcastReceiver所接收;android:process? ——broadcastReceiver運行所處的進程。默認為app的進程??梢灾付í毩⒌倪M程(Android四大基本組件都可以通過此屬性指定自己的獨立進程)

動態(tài)注冊

無須在AndroidManifest中注冊組件。直接在代碼中通過調(diào)用Context的registerReceiver函數(shù),可以在程序中動態(tài)注冊BroadcastReceiver。registerReceiver的定義形式如下:

registerReceiver(BroadcastReceiverreceiver,IntentFilterfilter)或:registerReceiver(BroadcastReceiverreceiver,IntentFilterfilter,StringbroadcastPermission,Handlerscheduler)

5、倆種注冊方式的區(qū)別

靜態(tài)注冊即使app退出,任然能接收到廣播

動態(tài)注冊時,當activity退出,就接收不到廣播了

但是 靜態(tài)注冊即使app退出,任然能接收到廣播 這種說法自Android 3.1開始有可能不再成立。

Android 3.1開始系統(tǒng)在Intent與廣播相關的flag增加了參數(shù):

A. FLAG_INCLUDE_STOPPED_PACKAGES:包含已經(jīng)停止的包(停止:即包所在的進程已經(jīng)退出)

B. FLAG_EXCLUDE_STOPPED_PACKAGES:不包含已經(jīng)停止的包

自Android3.1開始,系統(tǒng)本身則增加了對所有app當前是否處于運行狀態(tài)的跟蹤。在發(fā)送廣播時,不管是什么廣播類型,系統(tǒng)默認直接增加了值為FLAG_EXCLUDE_STOPPED_PACKAGES的flag,導致即使是靜態(tài)注冊的廣播接收器,對于其所在進程已經(jīng)退出的app,同樣無法接收到廣播。

由此,對于系統(tǒng)廣播,由于是系統(tǒng)內(nèi)部直接發(fā)出,無法更改此intent flag值,因此,3.1開始對于靜態(tài)注冊的接收系統(tǒng)廣播的BroadcastReceiver,如果App進程已經(jīng)退出,將不能接收到廣播。

但是對于自定義的廣播,可以通過復寫此flag為FLAG_INCLUDE_STOPPED_PACKAGES,使得靜態(tài)注冊的BroadcastReceiver,即使所在App進程已經(jīng)退出,也能能接收到廣播,并會啟動應用進程,但此時的BroadcastReceiver是重新新建的。

Intent intent = new Intent();

intent.setAction(BROADCAST_ACTION);

intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);

intent.putExtra("name", "qqyumidi");

sendBroadcast(intent);

替代方案: 通過將Service與App本身設置成不同的進程已經(jīng)成為實現(xiàn)此類需求的可行替代方案。

6、其他

有序廣播

有序廣播的有序廣播中的“有序”是針對廣播接收者而言的,指的是發(fā)送出去的廣播被BroadcastReceiver按照先后循序接收。有序廣播的定義過程與普通廣播無異,只是其的主要發(fā)送方式變?yōu)椋簊endOrderedBroadcast(intent, receiverPermission, ...)。

對于有序廣播,其主要特點總結如下:

1>多個具當前已經(jīng)注冊且有效的BroadcastReceiver接收有序廣播時,是按照先后順序接收的,先后順序判定標準遵循為:將當前系統(tǒng)中所有有效的動態(tài)注冊和靜態(tài)注冊的BroadcastReceiver按照priority屬性值從大到小排序,對于具有相同的priority的動態(tài)廣播和靜態(tài)廣播,動態(tài)廣播會排在前面。

2>先接收的BroadcastReceiver可以對此有序廣播進行截斷,使后面的BroadcastReceiver不再接收到此廣播,也可以對廣播進行修改,使后面的BroadcastReceiver接收到廣播后解析得到錯誤的參數(shù)值。當然,一般情況下,不建議對有序廣播進行此類操作,尤其是針對系統(tǒng)中的有序廣播。

應用內(nèi)廣播

Android中的廣播可以跨進程甚至跨App直接通信,且注冊是exported對于有intent-filter的情況下默認值是true,所以安全隱患如下:

其他App可能會針對性的發(fā)出與當前App intent-filter相匹配的廣播,由此導致當前App不斷接收到廣播并處理;

其他App可以注冊與當前App一致的intent-filter用于接收廣播,獲取廣播具體信息。

7、增加安全性的方案:

對于同一App內(nèi)部發(fā)送和接收廣播,將exported屬性人為設置成false,使得非本App內(nèi)部發(fā)出的此廣播不被接收;

在廣播發(fā)送和接收時,都增加上相應的permission,用于權限驗證;

發(fā)送廣播時,指定特定廣播接收器所在的包名,具體是通過intent.setPackage(packageName)指定在,這樣此廣播將只會發(fā)送到此包中的App內(nèi)與之相匹配的有效廣播接收器中。

相比于全局廣播,App應用內(nèi)廣播優(yōu)勢體現(xiàn)在:

安全性更高;

8、Android引入廣播機制的用意?

答:

a : 從MVC的角度考慮(應用程序內(nèi)) ,其實回答這個問題的時候還可以這樣問,android為什么要有那4大組件,現(xiàn)在的移動開發(fā)模型基本上也是照搬的web那一套MVC架構,只不過是改了點嫁妝而已。android的四大組件本質(zhì)上就是為了實現(xiàn)移動或者說嵌入式設備上的MVC架構,它們之間有時候是一種相互依存的關系,有時候又是一種補充關系,引入廣播機制可以方便幾大組件的信息和數(shù)據(jù)交互。

b:程序間互通消息(例如在自己的應用程序內(nèi)監(jiān)聽系統(tǒng)來電)

c:效率上(參考UDP的廣播協(xié)議在局域網(wǎng)的方便性)

d:設計模式上(反轉控制的一種應用,類似監(jiān)聽者模式)


五、ContentProvider

ContentProvider是一種數(shù)據(jù)共享組件,用于向其他組件和其他應用共享數(shù)據(jù)。同樣無法直接被用戶感知。

1、ContentProvider的URI的配置?

清單文件之指定URI或者代碼里面指定URI,contentProvider通過URI訪問數(shù)據(jù)

2、contentprovider怎么實現(xiàn)數(shù)據(jù)共享?

一個程序可以通過實現(xiàn)一個Content provider的抽象接口將自己的數(shù)據(jù)完全暴露出去,而且Content providers是以類似數(shù)據(jù)庫中表的方式將數(shù)據(jù)暴露。Content providers存儲和檢索數(shù)據(jù),通過它可以讓所有的應用程序訪問到,這也是應用程序之間唯一共享數(shù)據(jù)的方法。要想使應用程序的數(shù)據(jù)公開化,可通過2種方法:創(chuàng)建一個屬于你自己的Content provider或者將你的數(shù)據(jù)添加到一個已經(jīng)存在的Content provider中,前提是有相同數(shù)據(jù)類型并且有寫入Content provider的權限。

3、如何通過一套標準及統(tǒng)一的接口獲取其他應用程序暴露的數(shù)據(jù)?

Android提供了ContentResolver,外界的程序可以通過ContentResolver接口訪問ContentProvider提供的數(shù)據(jù)。

4、ContentProvider和SQL的區(qū)別

Sql只能在該工程的內(nèi)部共享數(shù)據(jù),ContentProvider能在工程之間實現(xiàn)數(shù)據(jù)共享。

5、Android如何訪問自定義ContentProvider

第一:得到ContentResolver類對象:ContentResolver cr = getContentResolver();

第二:定義要查詢的字段String數(shù)組。

第三:使用cr.query();返回一個Cursor對象。

第四:使用while循環(huán)得到Cursor里面的內(nèi)容


補充:

1、Intent的原理

intent是連接Activity, Service, BroadcastReceiver, ContentProvider四大組件的信使,,可以傳遞八種基本數(shù)據(jù)類型以及string, Bundle類型,以及實現(xiàn)了Serializable或者Parcelable的類型。

2、Intent可以劃分成顯式意圖和隱式意圖:

顯式意圖:調(diào)用Intent.setComponent()或Intent.setClass()方法明確指定了組件名的Intent為顯式意圖,顯式意圖明確指定了Intent應該傳遞給哪個組件。

隱式意圖:沒有明確指定組件名的Intent為隱式意圖。 Android系統(tǒng)會根據(jù)隱式意圖中設置的動作(action)、類別(category)、數(shù)據(jù)(URI和數(shù)據(jù)類型)找到最合適的組件來處理這個意圖。

3、IntentService有何優(yōu)點?

Acitivity的進程,當處理Intent的時候,會產(chǎn)生一個對應的Service

Android的進程處理器現(xiàn)在會盡可能的不kill掉你

非常容易使用。

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容