一圖解惑之Android調(diào)用ContentProvider基本流程

準(zhǔn)備

  • 基本使用
    ContentProvider作為四大組件之一坞琴,在開發(fā)過程中經(jīng)常被使用到翎卓。我們的常規(guī)做法是定義一個ContentProvider埋心,然后在使用的時候使用ContentResolver提供的接口來訪問數(shù)據(jù)。一個進(jìn)程可以訪問自己定義的ContentProvider韭赘,也可以訪問其他進(jìn)程定義的ContentProvider筒捺。
  • ContentProviderHolder:
    ContentProviderHolder是定義在IActivityManager類中的內(nèi)部類,它的作用主要是承載ContentProvider的信息和ContentProvider接口內(nèi)容纸厉,并在SystemServer和App進(jìn)程間傳遞系吭。其主要成員變量如下:
    1. info :ProviderInfo 描述該ContentProvider的信息。
    2. provider :IContentProvider 描述該ContentProvider對應(yīng)的ContentProvider接口颗品,它是一個Binder代理對象肯尺。
  • 大致流程:假設(shè)App B定義了一個ContentProvider,App A需要訪問該ContentProvider躯枢。整個調(diào)用過程簡單梳理會經(jīng)過以下幾個步驟:
    1. App A先向SystemServer查詢要訪問的ContentProvider接口则吟。
    2. SystemServer將查詢到的ContentProvider接口返回給App ,該ContentProvider接口是定義在App B中的ContentProvider的Binder代理锄蹂。
    3. App A再通過該Binder代理調(diào)用定義在App B中的ContentProvider的邏輯氓仲。
  • 本地緩存:ActivityThread內(nèi)部會緩存當(dāng)前進(jìn)程已經(jīng)訪問過的ContentProvider或者是當(dāng)前進(jìn)程內(nèi)自己定義的ContentProvider。緩存在其成員變量mProviderMap中得糜。這里注意參考上一篇一圖解惑對比區(qū)分敬扛,在AMS中也有個同名的成員變量mProviderMap,可以大致理解為他們都用來緩存ContentProvider接口朝抖,只不過一個是在本地進(jìn)程中緩存啥箭,一個是在SystemServer中全局緩存。

上圖

這次不墨跡治宣,先上圖再說:


Provider時序圖 (1).png

查看原圖

圖中每個步驟都標(biāo)了序號急侥,整個過程涉及到3個進(jìn)程間的通信砌滞。App A是ContentProvider的使用方,App B是ContentProvider的定義方坏怪,SystemServer是系統(tǒng)進(jìn)程贝润。下面就按序號順序做簡要說明。
簡要總結(jié):
1.業(yè)務(wù)邏輯層通過直接使用ContentResolver提供的接口去訪問數(shù)據(jù)(如query陕悬,insert等等)题暖。
2.ContentResolver需要獲取到ContentProvider接口才能對該ContentProvider訪問,所以這里ContentResolver先通過ActivityThread去獲取一個ContentProvider接口捉超。
3.上面提到ActivityThread的mProviderMap成員會緩存已經(jīng)獲取的ContentProvider接口或定義在自己進(jìn)程內(nèi)的ContentProvider接口胧卤。所以在這里ActivityThread會先通過acquireExistingProvider()方法在本地查找是否已有緩存。如果有拼岳,則直接跳到第13步返回結(jié)果給ContentResolver枝誊。如果沒有則會繼續(xù)通過進(jìn)程間通信向SystemServer中的AMS模塊查詢ContentProvider接口。
4.向AMS查詢ContentProvider接口惜纸。在AMS的mProviderMap成員中保存了當(dāng)前運(yùn)行的ContentProvider接口叶撒,查詢過程中大方向會有兩個分支:如果要查詢的ContentProvider接口不在mProviderMap緩存中,則一般情況下也說明該ContentProviders所在的進(jìn)程還沒啟動耐版,則繼續(xù)往下執(zhí)行第5步啟動該進(jìn)程祠够。否則直接跳到第12步,將從mProviderMap成員中查詢到的結(jié)果返回給ActivityThread粪牲。
5.啟動要查找的ContentProvider所在的進(jìn)程古瓤。接下來便是大家熟知的應(yīng)用進(jìn)程啟動的過程。這里主要關(guān)注第10步和第11步腺阳。
6~9.應(yīng)用進(jìn)程啟動初始化過程中與AMS的一系列交互落君。
10.通過調(diào)用installContentProviders()方法本地安裝ContentProvider,這里可以簡單理解所謂本地安裝就是填充ActivityThread中保存ContentProvider接口的緩存亭引,但是要注意當(dāng)前的ActivityThread是表示定義ContentProvider的進(jìn)程(App B)绎速,而不是使用ContentProvider的進(jìn)程(App A)。
11.回調(diào)AMS的publishContentProviders()方法焙蚓,將ContentProvider接口傳給AMS纹冤。至此AMS內(nèi)部的mProviderMap成員也獲取到了ContentProvider接口并保存。當(dāng)下次有進(jìn)程再請求訪問同一個ContentProvider接口時购公,就可以直接從AMS的mProviderMap成員中獲取該ContentProvider接口直接返回給調(diào)用方了赵哲。
12.返回查詢結(jié)果給ContentProvider的使用方(App A)缴守。這里要注意返回的數(shù)據(jù)類型是ContentProviderHolder眷茁,它繼承了Parcelable接口。因此可以在進(jìn)程間傳遞雏婶,使用方需要的ContentProvider接口就保存在其成員變量provider中绘闷。
13.ContentProvider的使用方將查找回來的ContentProvider接口返回給ContentResolver橡庞。
14.ContentResolver通過ContentProvider接口再次發(fā)起B(yǎng)inder通信向真正ContentProvider的實現(xiàn)方(App B)發(fā)送數(shù)據(jù)訪問請求较坛。
15.ContentProvider實現(xiàn)方(App B)將數(shù)據(jù)返回給Content使用方(App A)。
16.ContentResolver完成數(shù)據(jù)的訪問工作扒最,將查詢結(jié)果返回給業(yè)務(wù)邏輯層丑勤。

整個過程有可能只涉及一個進(jìn)程(App A),比如以下幾種情況:

  • ContentProvider的使用方(App A)已經(jīng)有要訪問的ContentProvider接口的緩存吧趣。
  • ContentProvider的定義與使用在相同的進(jìn)程法竞。

也可能涉及兩個進(jìn)程(App A和SystemServer):

  • ContentProvider的定義與使用在不同的進(jìn)程,但是AMS中已經(jīng)有該ContentProvider接口的緩存强挫。

也可能涉及三個進(jìn)程(App A岔霸,App B和SystemServer):

  • ContentProvider的定義與使用在不同的進(jìn)程,并且AMS中也沒有該ContentProvider接口的緩存俯渤。

And Then

我的分析默認(rèn)是按照Android N原代碼的邏輯來分析的呆细。如果在國產(chǎn)機(jī)上發(fā)現(xiàn)邏輯與之有沖突不要驚慌,國產(chǎn)機(jī)ROM在AOSP基礎(chǔ)上做了很多“優(yōu)化”八匠⌒跻或者不同的Android版本之間可能也存在微小差別。比如我的測試過程中就發(fā)現(xiàn)手上一臺華為在App B定義了ContentProvider梨树,但是App B進(jìn)程還沒有啟動時坑夯,App A使用該ContentProvider并不會把App B拉起,而是拋一個Warning:Unknown URL content://xxxxxxxxxxxxx抡四。
四大組件中之所以沒有先寫Activity和Broadcast是因為網(wǎng)上他們哥兩的介紹相對多的多柜蜈。不過后面我也會抽空把一圖解惑系列的四大組件都補(bǔ)全。一圖解惑系列的目的是希望盡量簡單直接的將基本的原理邏輯說清楚床嫌,如果需要了解內(nèi)部細(xì)節(jié),當(dāng)然還是需要Read The Fucking Source Code胸私。

Thank you~

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末厌处,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子岁疼,更是在濱河造成了極大的恐慌阔涉,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,948評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件捷绒,死亡現(xiàn)場離奇詭異瑰排,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)暖侨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,371評論 3 385
  • 文/潘曉璐 我一進(jìn)店門椭住,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人字逗,你說我怎么就攤上這事京郑≌悖” “怎么了?”我有些...
    開封第一講書人閱讀 157,490評論 0 348
  • 文/不壞的土叔 我叫張陵些举,是天一觀的道長跟狱。 經(jīng)常有香客問我,道長户魏,這世上最難降的妖魔是什么驶臊? 我笑而不...
    開封第一講書人閱讀 56,521評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮叼丑,結(jié)果婚禮上关翎,老公的妹妹穿的比我還像新娘。我一直安慰自己幢码,他們只是感情好笤休,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,627評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著症副,像睡著了一般店雅。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上贞铣,一...
    開封第一講書人閱讀 49,842評論 1 290
  • 那天闹啦,我揣著相機(jī)與錄音,去河邊找鬼辕坝。 笑死窍奋,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的酱畅。 我是一名探鬼主播琳袄,決...
    沈念sama閱讀 38,997評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼纺酸!你這毒婦竟也來了窖逗?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,741評論 0 268
  • 序言:老撾萬榮一對情侶失蹤餐蔬,失蹤者是張志新(化名)和其女友劉穎碎紊,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體樊诺,經(jīng)...
    沈念sama閱讀 44,203評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡仗考,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,534評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了词爬。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片秃嗜。...
    茶點(diǎn)故事閱讀 38,673評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出痪寻,到底是詐尸還是另有隱情螺句,我是刑警寧澤,帶...
    沈念sama閱讀 34,339評論 4 330
  • 正文 年R本政府宣布橡类,位于F島的核電站蛇尚,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏顾画。R本人自食惡果不足惜取劫,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,955評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望研侣。 院中可真熱鬧谱邪,春花似錦、人聲如沸庶诡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,770評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽末誓。三九已至扯俱,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間喇澡,已是汗流浹背迅栅。 一陣腳步聲響...
    開封第一講書人閱讀 32,000評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留晴玖,地道東北人读存。 一個月前我還...
    沈念sama閱讀 46,394評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像呕屎,于是被迫代替她去往敵國和親让簿。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,562評論 2 349

推薦閱讀更多精彩內(nèi)容

  • AndroidSmall框架是android中一個非常優(yōu)秀的插件化框架秀睛,有時我們不僅要學(xué)會使用它尔当,也要去理解它的原...
    柴犬大人閱讀 1,240評論 0 6
  • 沒有勤于筆耕,是我對自己的批評琅催。雖然我仍然追求精神上的充盈居凶,但是疏于記錄卻是自我的放縱虫给,這是2017年年終總結(jié)首先...
    悠游四海閱讀 282評論 6 5
  • 第一次見到楊海藤抡,是2013年的時候了。那年春天抹估,我依父母之命回家相親缠黍。母親大人一直在我耳邊說男方多好多好,某某名校...
    老狼叔叔閱讀 5,705評論 1 4
  • 喜歡你心無旁騖的樣子替饿。 這是名為花兒app上的主題語。軟件上的花畫得樸素而美麗贸典,帶著孩童稚嫩的視角描摹著每朵意義不...
    虛谷沉香閱讀 452評論 1 1
  • python允許函數(shù)從調(diào)用語句中收集任意數(shù)量的實參视卢。 大大: 函數(shù)就好比是你厭倦了重復(fù)差不多內(nèi)容的功能,這些功能都...
    三千院賀Hall閱讀 343評論 1 0