Android有四大組件:Activity、Service、Broadcast Receiver、Content Provider

在這些組件之間的通訊中,主要是由Intent協助完成的。
Intent負責對應用中一次操作的動作、動作涉及數據、附加數據進行描述,Android則根據此Intent的描述,負責找到對應的組件,將 Intent傳遞給調用的組件,並完成組件的調用。
因此,Intent在這裏起着一個媒體中介的作用,專門提供組件互相調用的相關信息,實現調用者與被調用者之間的解耦。

Android有四大組件:Activity、Service、Broadcast Receiver、Content Provider
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,使用<service></service>標籤。
(4)Service通常位於後臺運行,它一般不需要與用戶交互,因此Service組件沒有圖形用戶界面。Service組件需要繼承Service基類。Service組件通常用於爲其他組件提供後臺服務或監控其他組件的運行狀態。
3、content provider
(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關掉後,廣播也就失效了。靜態註冊無需擔憂廣播接收器是否被關閉,只要設備是開啓狀態,廣播接收器也是打開着的。

Android 開發的四大組件分別是:活動(activity),用於表現功能;服務(service),後臺運行服務,不提供界面呈現;廣播接受者(Broadcast Receive),勇於接收廣播;內容提供者(Content Provider),支持多個應用中存儲和讀取數據,相當於數據庫。

1.活動(activity)

(1)定義:Activity是Android的四大組件之一。是用戶操作的可視化界面;它爲用戶提供了一個完成操作指令的窗口。當我們創建完畢Activity之後,需要調用setContentView()方法來完成界面的顯示;以此來爲用戶提供交互的入口。在Android App 中只要能看見的幾乎都要依託於Activity,所以Activity是在開發中使用最頻繁的一種組件。

 

(2)一個Activity通常就是一個單獨的屏幕(窗口)。

(3)Activity之間通過Intent進行通信。

(4)android應用中每一個Activity都必須要在AndroidManifest.xml配置文件中聲明,否則系統將不識別也不執行該Activity。在android stdio會自動生成,但eclipse需要自己手動添加

(5)Activity的生命週期
      在Android中會維持一個Activity Stack(Activity棧),當一個新的Activity創建時,它就會放到棧頂,這個Activity就處於運行狀態。當再有一個新的Activity被創建後,會重新壓人棧頂,而之前的Activity則會在這個新的Activity底下,就像槍梭壓入子彈一樣。而且之前的Activity就會進入後臺。
一個Activity實質上有四種狀態:
a.運行中(Running/Active):這時Activity位於棧頂,是可見的,並且可以用戶交互。
b.暫停(Paused):當Activity失去焦點,不能跟用戶交互了,但依然可見,就處於暫停狀態。當一個新的非全屏的Activity或者一個透明的Activity放置在棧頂,Activity就處於暫停狀態;這個時候Activity的各種數據還被保持着;只有在系統內存在極低的狀態下,系統纔會自動的去銷燬Activity。
c.停止(Stoped):當一個Activity被另一個Activity完全覆蓋,或者點擊HOME鍵退入了後臺,這時候Activity處於停止狀態。這裏有些是跟暫停狀態相似的:這個時候Activity的各種數據還被保持着;當系統的別的地方需要用到內容時,系統會自動的去銷燬Activity。
d.銷燬(Detroyed):當我們點擊返回鍵或者系統在內存不夠用的情況下就會把Activity從棧裏移除銷燬,被系統回收,這時候,Activity處於銷燬狀態。

 

2.服務(Service)

 

service(服務)是安卓中的四大組件之一,它通常用作在後臺處理耗時的邏輯,與Activity一樣,它存在自己的生命週期,也需要在AndroidManifest.xml配置相關信息。

服務(Service)是Android中實現程序後臺運行的解決方案,它非常適合去執行那些不需要和用戶交互而且還要求長期運行的任務。服務的運行不依賴於任何用戶界面,即使程序被切換到後臺,或者用戶打開了另外一個應用程序,服務仍然能夠保持正常運行。

不過需要注意的是,服務並不是運行在一個獨立的進程當中的,而是依賴於創建服務時所在的應用程序進程。與某個應用程序進程被殺掉時,所有依賴於該進程的服務也會停止運行。另外.也不要被服務的後臺概念所迷惑,實際上服務並不會自動開啓線程,所有的代碼都是默認運行在主線程當中的。也就是說,我們需要在服務的內部手動創建子線程,並在這裏執行具體的任務,否則就有可能出現主線程被阻塞住的情況。

(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,使用<service></service>標籤。

(4)Service通常位於後臺運行,它一般不需要與用戶交互,因此Service組件沒有圖形用戶界面。Service組件需要繼承Service基類。Service組件通常用於爲其他組件提供後臺服務或監控其他組件的運行狀態。

定義

 

Service是一個專門在後臺處理長時間任務的Android組件,它沒有UI。它有兩種啓動方式,startService和bindService。

 這兩種啓動方式的區別:

startService只是啓動Service,啓動它的組件(如Activity)和Service並沒有關聯,只有當Service調用stopSelf或者其他組件調用stopService服務纔會終止。
bindService方法啓動Service,其他組件可以通過回調獲取Service的代理對象和Service交互,而這兩方也進行了綁定,當啓動方銷燬時,Service也會自動進行unBind操作,當發現所有綁定都進行了unBind時纔會銷燬Service。

Service的onCreate回調函數可以做耗時的操作嗎?
不可以,Service的onCreate是在主線程(ActivityThread)中調用的,耗時操作會阻塞UI

 

如果需要做耗時的操作,你會怎麼做?

線程和Handler方式

是否知道IntentService,在什麼場景下使用IntentService?

 IntentService相比父類Service而言,最大特點是其回調函數onHandleIntent中可以直接進行耗時操作,不必再開線程。其原理是IntentService的成員變量 Handler在初始化時已屬於工作線程,之後handleMessage,包括onHandleIntent等函數都運行在工作線程中。

如果對IntentService的瞭解僅限於此,會有種IntentService很雞肋的觀點,因爲在Service中開線程進行耗時操作也不麻煩。我當初也是這個觀點,所以很少用IntentService。

    但是IntentService還有一個特點,就是多次調用onHandleIntent函數(也就是有多個耗時任務要執行),多個耗時任務會按順序依次執行。原理是其內置的Handler關聯了任務隊列,Handler通過looper取任務執行是順序執行的。

    這個特點就能解決多個耗時任務需要順序依次執行的問題。而如果僅用service,開多個線程去執行耗時操作,就很難管理。

 


https://blog.csdn.net/zhengyin_tmac/article/details/52446696

 

3.廣播接受者(Broadcast Receive)
 

在Android中,廣播是一種廣泛運用的在應用程序之間傳輸信息的機制。而廣播接收器是對發送出來的廣播進行過濾接受並響應的一類組件。可以使用廣播接收器來讓應用對一個外部時間做出響應。例如,當電話呼入這個外部事件到來時,可以利用廣播接收器進行處理。當下載一個程序成功完成時,仍然可以利用廣播接收器進行處理。廣播接收器不NotificationManager來通知用戶這些事情發生了。廣播接收器既可以在AndroidManifest.xml中註冊,也可以在運行時的代碼中使用Context.registerReceive()進行註冊。只要是註冊了,當事件來臨時,即使程序沒有啓動,系統也在需要的時候啓動程序。各種應用還可以通過使用Context.sendBroadcast()將它們自己的Intent廣播給其他應用程序。

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

(2)廣播接收者的註冊有兩種方法,分別是程序動態註冊(在運行時的代碼中使用Context.registerReceive()進行註冊)和AndroidManifest文件中進行靜態註冊。

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

4.內容提供者(Content Provider)

 (1)android平臺提供了Content Provider使一個應用程序的指定數據集提供給其他應用程序。其他應用可以通過ContentResolver類從該內容提供者中獲取或存入數據。
(2)只有需要在多個應用程序間共享數據是才需要內容提供者。例如,通訊錄數據被多個應用程序使用,且必須存儲在一個內容提供者中。它的好處是統一數據訪問方式。
(3)ContentProvider實現數據共享。ContentProvider用於保存和獲取數據,並使其對所有應用程序可見。這是不同應用程序間共享數據的唯一方式,因爲android沒有提供所有應用共同訪問的公共存儲區。
(4)開發人員不會直接使用ContentProvider類的對象,大多數是通過ContentResolver對象實現對ContentProvider的操作。

(5)ContentProvider使用URI來唯一標識其數據集,這裏的URI以content://作爲前綴,表示該數據由ContentProvider來管理。

 

 

 

 

emmm看到就收集我也忘記哪是哪個網的了

 

面試題:有使用過ContentProvider碼?能說說Android爲什麼要設計ContentProvider這個組件嗎?

ContentProvider應用程序間非常通用的共享數據的一種方式,也是Android官方推薦的方式。Android中許多系統應用都使用該方式實現數據共享,比如通訊錄、短信等。但我遇到很多做Android開發的人都不怎麼使用它,覺得直接讀取數據庫會更簡單方便。

那麼Android搞一個內容提供者在數據和應用之間,只是爲了裝高大上,故弄玄虛?我認爲其設計用意在於:

  1. 封裝。對數據進行封裝,提供統一的接口,使用者完全不必關心這些數據是在DB,XML、Preferences或者網絡請求來的。當項目需求要改變數據來源時,使用我們的地方完全不需要修改。
  1. 提供一種跨進程數據共享的方式。

應用程序間的數據共享還有另外的一個重要話題,就是數據更新通知機制了。因爲數據是在多個應用程序中共享的,當其中一個應用程序改變了這些共享數據的時候,它有責任通知其它應用程序,讓它們知道共享數據被修改了,這樣它們就可以作相應的處理。

ContentResolver接口的notifyChange函數來通知那些註冊了監控特定URI的ContentObserver對象,使得它們可以相應地執行一些處理。ContentObserver可以通過registerContentObserver進行註冊。

既然是對外提供數據共享,那麼如何限制對方的使用呢?

android:exported屬性非常重要。這個屬性用於指示該服務是否能夠被其他應用程序組件調用或跟它交互。如果設置爲true,則能夠被調用或交互,否則不能。設置爲false時,只有同一個應用程序的組件或帶有相同用戶ID的應用程序才能啓動或綁定該服務。

對於需要開放的組件應設置合理的權限,如果只需要對同一個簽名的其它應用開放content provider,則可以設置signature級別的權限。大家可以參考一下系統自帶應用的代碼,自定義了signature級別的permission:

        <permission android:name="com.android.gallery3d.filtershow.permission.READ"
                    android:protectionLevel="signature" />

        <permission android:name="com.android.gallery3d.filtershow.permission.WRITE"
                    android:protectionLevel="signature" />

        <provider
            android:name="com.android.gallery3d.filtershow.provider.SharedImageProvider"
            android:authorities="com.android.gallery3d.filtershow.provider.SharedImageProvider"
            android:grantUriPermissions="true"
            android:readPermission="com.android.gallery3d.filtershow.permission.READ"
            android:writePermission="com.android.gallery3d.filtershow.permission.WRITE" />

如果我們只需要開放部份的URI給其他的應用訪問呢?可以參考Provider的URI權限設置,只允許訪問部份URI,可以參考原生ContactsProvider2的相關代碼(注意path-permission這個選項):

        <provider android:name="ContactsProvider2"
            android:authorities="contacts;com.android.contacts"
            android:label="@string/provider_label"
            android:multiprocess="false"
            android:exported="true"
            android:grantUriPermissions="true"
            android:readPermission="android.permission.READ_CONTACTS"
            android:writePermission="android.permission.WRITE_CONTACTS">
            <path-permission
                    android:pathPrefix="/search_suggest_query"
                    android:readPermission="android.permission.GLOBAL_SEARCH" />
            <path-permission
                    android:pathPrefix="/search_suggest_shortcut"
                    android:readPermission="android.permission.GLOBAL_SEARCH" />
            <path-permission
                    android:pathPattern="/contacts/.*/photo"
                    android:readPermission="android.permission.GLOBAL_SEARCH" />
            <grant-uri-permission android:pathPattern=".*" />
        </provider>

ContentProvider接口方法運行在哪個線程中呢?

ContentProvider可以在AndroidManifest.xml中配置一個叫做android:multiprocess的屬性,默認值是false,表示ContentProvider是單例的,無論哪個客戶端應用的訪問都將是同一個ContentProvider對象,如果設爲true,系統會爲每一個訪問該ContentProvider的進程創建一個實例。

這點還是比較好理解的,那如果我要問每個ContentProvider的操作是在哪個線程中運行的呢(其實我們關心的是UI線程和工作線程)?比如我們在UI線程調用getContentResolver().query查詢數據,而當數據量很大時(或者需要進行較長時間的計算)會不會阻塞UI線程呢?

要分兩種情況回答這個問題:

  1. ContentProvider和調用者在同一個進程,ContentProvider的方法(query/insert/update/delete等)和調用者在同一線程中;
  1. ContentProvider和調用者在不同的進程,ContentProvider的方法會運行在它自身所在進程的一個Binder線程中。

但是,注意這兩種方式在ContentProvider的方法沒有執行完成前都會blocked調用者。所以你應該知道這個上面這個問題的答案了吧。

也可以看看CursorLoader這個類的源碼,看Google自己是怎麼使用getContentResolver().query的。

ContentProvider是如何在不同應用程序之間傳輸數據的?

這個問題點有些深入,大家要對Binder進程間通信機制比較瞭解。因爲之前我們有提到過一個應用進程有16個Binder線程去和遠程服務進行交互,而每個線程可佔用的緩存空間是128KB這樣,超過會報異常。ContentResolver雖然是通過Binder進程間通信機制打通了應用程序之間共享數據的通道,但Content Provider組件在不同應用程序之間傳輸數據是基於匿名共享內存機制來實現的。有興趣的可以查看一下老羅的文章Android系統匿名共享內存Ashmem(Anonymous Shared Memory)簡要介紹和學習計劃

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章