android四大組件:Activity,Service,BroadcastReceiver和ContentProvider.
一、異同點
android的四大組件組件中,除了BroadcastReceiver以外,其他的三種都必須在Android-Manifest中注冊,對于BroadcastReceiver來說,他可以在Android-Manifest中注冊,也可以通過代碼來注冊。在調用方式上,Activity,Service,和、BroadcastReceiver需要借助Intent,而ContentProvider不需要。
二、Activity的相關介紹
Activity是一種展示組件,用于向用戶直接的展示一個界面,并且可以接收用戶輸入的信息來進行交互。
1、什么是Activity?
Activity是一個負責與用戶交互的組件,Activity中所有操作都與用戶密切相關,可以通過setContentView(View)來顯示指定控件。
在一個android應用中,一個Activity通常就是一個單獨的屏幕,它上面可以顯示一些控件也可以監聽并處理用戶的事件做出響應。
2、請描述一下Activity生命周期。
onCreate(Bundle savedInstanceState):
創建activity時調用。設置在該方法中,還以Bundle的形式提供對以前儲存的任何狀態的訪問!
onStart():
activity變為在屏幕上對用戶可見時調用。
onResume():
activity開始與用戶交互時調用(無論是啟動還是重新啟動一個活動,該方法
總是被調用的)。
onPause():
activity被暫停或收回cpu和其他資源時調用,該方法用于保存活動狀態的,也
是保護現場,壓棧吧!
onStop():
activity被停止并轉為不可見階段及后續的生命周期事件時調用。
onRestart():
重新啟動activity時調用。該活動仍在棧中,而不是啟動新的活動。
onDestroy():
activity被完全從系統內存中移除時調用,該方法被調用
3、如何退出Activity?如何安全退出已調用多個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由于某原因被系統回收了,如何在被系統回收之前保存當前狀態?
答:重寫onSaveInstanceState()方法,在此方法中保存需要保存的數據,該方法將會在activity被回收之前調用。通過重寫onRestoreInstanceState()方法可以從中提取保存好的數據
5、?activity在屏幕旋轉時的生命周期
答:不設置Activity的android:configChanges時,切屏會重新調用各個生命周期,切橫屏時會執行一次,切豎屏時會執行兩次;設置Activity的android:configChanges="orientation"時,切屏還是會重新調用各個生命周期,切橫、豎屏時只會執行一次;設置Activity的android:configChanges="orientation|keyboardHidden"時,切屏不會重新調用各個生命周期,只會執行onConfigurationChanged方法。
6、?activity的啟動模式有哪些?是什么含義?
答:在android里,有4種activity的啟動模式,分別為:
“standard” (默認)
“singleTop”
“singleTask”
“singleInstance”
當應用運行起來后就會開啟一條線程,線程中會運行一個任務棧,當Activity實例創建后就會放入任務棧中。Activity啟動模式的設置在AndroidManifest.xml文件中,通過配置Activity的屬性android:launchMode=""設置。
1. Standared模式(默認)
我們平時直接創建的Activity都是這種模式的Activity,這種模式的Activity的特點是:只要你創建了Activity實例,一旦激活該Activity,則會向任務棧中加入新創建的實例,退出Activity則會在任務棧中銷毀該實例。
2. SingleTop模式
這種模式會考慮當前要激活的Activity實例在任務棧中是否正處于棧頂,如果處于棧頂則無需重新創建新的實例,會重用已存在的實例,否則會在任務棧中創建新的實例。
3. SingleTask模式
如果任務棧中存在該模式的Activity實例,則把棧中該實例以上的Activity實例全部移除,調用該實例的newInstance()方法重用該Activity,使該實例處於棧頂位置,否則就重新創建一個新的Activity實例。
4. SingleInstance模式
當該模式Activity實例在任務棧中創建后,只要該實例還在任務棧中,即只要激活的是該類型的Activity,都會通過調用實例的newInstance()方法重用該Activity,此時使用的都是同一個Activity實例,它都會處于任務棧的棧頂。此模式一般用于加載較慢的,比較耗性能且不需要每次都重新創建的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總是保持相同的次序。這個標志一般用于呈現“啟動”類型的行為:它們提供用戶一系列可以單獨完成的事情,與啟動它們的Activity完全無關。
FLAG_ACTIVITY_CLEAR_TOP
如果設置,并且這個Activity已經在當前的Task中運行,因此,不再是重新啟動一個這個Activity的實例,而是在這個Activity上方的所有Activity都將關閉,然后這個Intent會作為一個新的Intent投遞到老的Activity(現在位于頂端)中。
FLAG_ACTIVITY_SINGLE_TOP
如果設置,并且這個Activity已經在當前的Task中運行,因此,不再是重新啟動一個這個Activity的實例,而是在這個Activity上方的所有Activity都將關閉,然后這個Intent會作為一個新的Intent投遞到老的Activity(現在位于頂端)中。
FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
如果設置這個標志,這個activity不管是從一個新的棧啟動還是從已有棧推到棧頂,它都將以the front door of the task的方式啟動。這就講導致任何與應用相關的棧都講重置到正常狀態(不管是正在講activity移入還是移除),如果需要,或者直接重置該棧為初始狀態。
三、Service
Service是一種計算型組件,用于在后臺執行一系列的計算任務。由于在后臺,所以用戶無法直接感知到他的存在。Service和activity組件略有不同,activity組件只有一種運行模式,即activity處于啟動狀態,而Service卻有兩種狀態:啟動和綁定狀態。
1、android 關于service生命周期的onCreate()和onStart()說法正確的是(ad)(多選題)
A、當第一次啟動的時候先后調用onCreate()和onStart()方法
B、當第一次啟動的時候只會調用onCreate()方法
C、如果service已經啟動,將先后調用onCreate()和onStart()方法
D、如果service已經啟動,只會執行onStart()方法,不在執行onCreate()方法
2、Service是如何啟動
A. 通過startService;Service會經歷onCreate->onStart;stopService的時候直接onDestroy;如果是調用者(TestServiceHolder)自己直接退出而沒有調用stopService的話,Service會一直在后臺運行,下次TestServiceHolder再起來可以stopService。
B. 通過bindService;Service只會運行onCreate,這個時候TestServiceHolder和TestService綁定在一起,TestServiceHolder退出了,Srevice就會調onUnbind->onDestroyed,所謂綁定在一起就共存亡了。
3、Service用在哪個線程
默認情況下Service是運行在啟動該Service的應用主線程的,如果Service中的操作占用大量的CPU資源或有阻斷操作(比如播放MP3或者訪問網絡)會影響應用主線程的響應性能,甚至會造成“應用程序無響應(ANR)”問題。
4、簡單介紹服務
服務是沒有界面的長生命周期的代碼。一個很好的例子是媒體播放器從列表中播放歌曲。在一個媒體播放器程序中,大概要有一個或多個活動(activity)來供用戶選擇歌曲并播放它。然而,音樂的回放就不能使用活動(activity)了,因為用戶希望他導航到其他界面時音樂繼續播放。這種情況下,媒體播放器活動(activity)要用Context.startService()啟動一個服務來在后臺運行保持音樂的播放。系統將保持這個音樂回放服務的運行直到它結束。注意一下,你要用Context.bindService()方法連接服務(如果它沒有運行,要先啟動它)。當連接到服務后,你可以通過服務暴露的一個接口和它通信。對于音樂服務,它允許你暫停、倒帶,等等。
5、service和Thread區別?
1).Thread:Thread 是程序執行的最小單元,它是分配CPU的基本單位。可以用 Thread 來執行一些異步的操作。
2).Service:Service 是android的一種機制,當它運行的時候如果是Local Service,那么對應的 Service 是運行在主進程的 main 線程上的。如:onCreate,onStart 這些函數在被系統調用的時候都是在主進程的 main 線程上運行的。如果是Remote Service,那么對應的 Service 則是運行在獨立進程的 main 線程上。
四、BroadcastReceiver
BroadcastReceiver是一種消息型組件,用于在不同的組件中和不同的應用之間傳遞消息。同樣無法被用戶指甲感知到,因為他工作在系統內部。
在Android中,Broadcast是一種廣泛運用的在應用程序之間傳輸信息的機制。
1、用途:
實現了不同的程序之間的數據傳輸與共享,因為只要是和發送廣播的action相同的接受者都能接受這個廣播。典型的應用就是android自帶的短信,電話等等廣播,只要我們實現了他們的action的廣播,那么我們就能接收他們的數據了,以便做出一些處理。比如說攔截系統短信,攔截騷擾電話等
起到了一個通知的作用,比如在service中要通知主程序,更新主程序的UI等
因為service是沒有界面的,所以不能直接獲得主程序中的控件,這樣我們就只能在主程序中實現一個廣播接受者專門用來接受service發過來的數據和通知了
2、使用場景:
同一app內部的同一組件內的消息通信(單個或多個線程之間);
同一app內部的不同組件之間的消息通信(單個進程);
同一app具有多個進程的不同組件之間的消息通信;
不同app之間的組件之間消息通信;
Android系統在特定情況下與App之間的消息通信。
3、實現原理:
從實現原理看上,Android中的廣播使用了觀察者模式,基于消息的發布/訂閱事件模型。因此,從實現的角度來看,Android中的廣播將廣播的發送者和接受者極大程度上解耦,使得系統能夠方便集成,更易擴展。具體實現流程要點粗略概括如下:
廣播接收者BroadcastReceiver通過Binder機制向AMS(Activity Manager Service)進行注冊;
廣播發送者通過binder機制向AMS發送廣播;
AMS查找符合相應條件(IntentFilter/Permission等)的BroadcastReceiver,將廣播發送到BroadcastReceiver(一般情況下是Activity)相應的消息循環隊列中;
消息循環執行拿到此廣播,回調BroadcastReceiver中的onReceive()方法。
4、注冊方式
有倆種注冊方式分別是靜態注冊和動態注冊
靜態注冊
在AndroidManifest.xml 中:? ? . . .android:exported —— 此broadcastReceiver能否接收其他App的發出的廣播(其默認值是由receiver中有無intent-filter決定的,如果有intent-filter,默認值為true,否則為false。)android:name? —— 此broadcastReceiver類名;android:permission? ——如果設置,具有相應權限的廣播發送方發送的廣播才能被此broadcastReceiver所接收;android:process? ——broadcastReceiver運行所處的進程。默認為app的進程。可以指定獨立的進程(Android四大基本組件都可以通過此屬性指定自己的獨立進程)
動態注冊
無須在AndroidManifest中注冊組件。直接在代碼中通過調用Context的registerReceiver函數,可以在程序中動態注冊BroadcastReceiver。registerReceiver的定義形式如下:
registerReceiver(BroadcastReceiverreceiver,IntentFilterfilter)或:registerReceiver(BroadcastReceiverreceiver,IntentFilterfilter,StringbroadcastPermission,Handlerscheduler)
5、倆種注冊方式的區別
靜態注冊即使app退出,任然能接收到廣播
動態注冊時,當activity退出,就接收不到廣播了
但是 靜態注冊即使app退出,任然能接收到廣播 這種說法自Android 3.1開始有可能不再成立。
Android 3.1開始系統在Intent與廣播相關的flag增加了參數:
A. FLAG_INCLUDE_STOPPED_PACKAGES:包含已經停止的包(停止:即包所在的進程已經退出)
B. FLAG_EXCLUDE_STOPPED_PACKAGES:不包含已經停止的包
自Android3.1開始,系統本身則增加了對所有app當前是否處于運行狀態的跟蹤。在發送廣播時,不管是什么廣播類型,系統默認直接增加了值為FLAG_EXCLUDE_STOPPED_PACKAGES的flag,導致即使是靜態注冊的廣播接收器,對于其所在進程已經退出的app,同樣無法接收到廣播。
由此,對于系統廣播,由于是系統內部直接發出,無法更改此intent flag值,因此,3.1開始對于靜態注冊的接收系統廣播的BroadcastReceiver,如果App進程已經退出,將不能接收到廣播。
但是對于自定義的廣播,可以通過復寫此flag為FLAG_INCLUDE_STOPPED_PACKAGES,使得靜態注冊的BroadcastReceiver,即使所在App進程已經退出,也能能接收到廣播,并會啟動應用進程,但此時的BroadcastReceiver是重新新建的。
Intent intent = new Intent();
intent.setAction(BROADCAST_ACTION);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
intent.putExtra("name", "qqyumidi");
sendBroadcast(intent);
替代方案: 通過將Service與App本身設置成不同的進程已經成為實現此類需求的可行替代方案。
6、其他
有序廣播
有序廣播的有序廣播中的“有序”是針對廣播接收者而言的,指的是發送出去的廣播被BroadcastReceiver按照先后循序接收。有序廣播的定義過程與普通廣播無異,只是其的主要發送方式變為:sendOrderedBroadcast(intent, receiverPermission, ...)。
對于有序廣播,其主要特點總結如下:
1>多個具當前已經注冊且有效的BroadcastReceiver接收有序廣播時,是按照先后順序接收的,先后順序判定標準遵循為:將當前系統中所有有效的動態注冊和靜態注冊的BroadcastReceiver按照priority屬性值從大到小排序,對于具有相同的priority的動態廣播和靜態廣播,動態廣播會排在前面。
2>先接收的BroadcastReceiver可以對此有序廣播進行截斷,使后面的BroadcastReceiver不再接收到此廣播,也可以對廣播進行修改,使后面的BroadcastReceiver接收到廣播后解析得到錯誤的參數值。當然,一般情況下,不建議對有序廣播進行此類操作,尤其是針對系統中的有序廣播。
應用內廣播
Android中的廣播可以跨進程甚至跨App直接通信,且注冊是exported對于有intent-filter的情況下默認值是true,所以安全隱患如下:
其他App可能會針對性的發出與當前App intent-filter相匹配的廣播,由此導致當前App不斷接收到廣播并處理;
其他App可以注冊與當前App一致的intent-filter用于接收廣播,獲取廣播具體信息。
7、增加安全性的方案:
對于同一App內部發送和接收廣播,將exported屬性人為設置成false,使得非本App內部發出的此廣播不被接收;
在廣播發送和接收時,都增加上相應的permission,用于權限驗證;
發送廣播時,指定特定廣播接收器所在的包名,具體是通過intent.setPackage(packageName)指定在,這樣此廣播將只會發送到此包中的App內與之相匹配的有效廣播接收器中。
相比于全局廣播,App應用內廣播優勢體現在:
安全性更高;
8、Android引入廣播機制的用意?
答:
a : 從MVC的角度考慮(應用程序內) ,其實回答這個問題的時候還可以這樣問,android為什么要有那4大組件,現在的移動開發模型基本上也是照搬的web那一套MVC架構,只不過是改了點嫁妝而已。android的四大組件本質上就是為了實現移動或者說嵌入式設備上的MVC架構,它們之間有時候是一種相互依存的關系,有時候又是一種補充關系,引入廣播機制可以方便幾大組件的信息和數據交互。
b:程序間互通消息(例如在自己的應用程序內監聽系統來電)
c:效率上(參考UDP的廣播協議在局域網的方便性)
d:設計模式上(反轉控制的一種應用,類似監聽者模式)
五、ContentProvider
ContentProvider是一種數據共享組件,用于向其他組件和其他應用共享數據。同樣無法直接被用戶感知。
1、ContentProvider的URI的配置?
清單文件之指定URI或者代碼里面指定URI,contentProvider通過URI訪問數據
2、contentprovider怎么實現數據共享?
一個程序可以通過實現一個Content provider的抽象接口將自己的數據完全暴露出去,而且Content providers是以類似數據庫中表的方式將數據暴露。Content providers存儲和檢索數據,通過它可以讓所有的應用程序訪問到,這也是應用程序之間唯一共享數據的方法。要想使應用程序的數據公開化,可通過2種方法:創建一個屬于你自己的Content provider或者將你的數據添加到一個已經存在的Content provider中,前提是有相同數據類型并且有寫入Content provider的權限。
3、如何通過一套標準及統一的接口獲取其他應用程序暴露的數據?
Android提供了ContentResolver,外界的程序可以通過ContentResolver接口訪問ContentProvider提供的數據。
4、ContentProvider和SQL的區別
Sql只能在該工程的內部共享數據,ContentProvider能在工程之間實現數據共享。
5、Android如何訪問自定義ContentProvider
第一:得到ContentResolver類對象:ContentResolver cr = getContentResolver();
第二:定義要查詢的字段String數組。
第三:使用cr.query();返回一個Cursor對象。
第四:使用while循環得到Cursor里面的內容
補充:
1、Intent的原理
intent是連接Activity, Service, BroadcastReceiver, ContentProvider四大組件的信使,,可以傳遞八種基本數據類型以及string, Bundle類型,以及實現了Serializable或者Parcelable的類型。
2、Intent可以劃分成顯式意圖和隱式意圖:
顯式意圖:調用Intent.setComponent()或Intent.setClass()方法明確指定了組件名的Intent為顯式意圖,顯式意圖明確指定了Intent應該傳遞給哪個組件。
隱式意圖:沒有明確指定組件名的Intent為隱式意圖。 Android系統會根據隱式意圖中設置的動作(action)、類別(category)、數據(URI和數據類型)找到最合適的組件來處理這個意圖。
3、IntentService有何優點?
Acitivity的進程,當處理Intent的時候,會產生一個對應的Service
Android的進程處理器現在會盡可能的不kill掉你
非常容易使用。