?(十二)ContentProvider
?(1)ContentProvider是什么?
? ContentProvider,簡(jiǎn)稱(chēng)CP。
?做App開(kāi)發(fā)的同學(xué),尤其是電商類(lèi)App,對(duì)CP并不熟悉,對(duì)這個(gè)概念的最大程度的了解,也僅僅是建立在書(shū)本上,它是Android四大組件中的一個(gè)。
?做系統(tǒng)管理類(lèi)的App,比如說(shuō)手機(jī)助手這種,有機(jī)會(huì)頻繁使用CP。
?而對(duì)于應(yīng)用類(lèi)App,數(shù)據(jù)通常存在服務(wù)器端,其它應(yīng)用類(lèi)App也想使用的時(shí)候,一般都是從服務(wù)器取數(shù)據(jù),所以沒(méi)機(jī)會(huì)使用到CP。
?有時(shí)候我們會(huì)在自己的App中讀取通信錄或者短信的數(shù)據(jù),這時(shí)候就需要用到CP了。通信錄或者短信的數(shù)據(jù),是以CP的形式提供的,我們?cè)贏pp這邊,是使用方。
?對(duì)于做應(yīng)用類(lèi)App的同學(xué),很少有機(jī)會(huì)自定義CP供其它App使用。
?我們快速回顧一下在App中怎么使用CP。
?1)定義CP的App1:
?在App1中定義一個(gè)CP的子類(lèi)MyContentProvider,并在Manifest中聲明,為此要在MyContentProvider中實(shí)現(xiàn)CP的增刪改查四個(gè)方法:
?2)使用CP的App2:
?在App2訪(fǎng)問(wèn)App1中定義的CP,為此,要使用到ContentResolver,它也提供了增刪改查4個(gè)方法,用于訪(fǎng)問(wèn)App1中定義的CP:
?首先我們看一下ContentResolver的增刪改查這4個(gè)方法的底層實(shí)現(xiàn),其實(shí)都是和AMS通信,最終調(diào)用App1的CP的增刪改查4個(gè)方法,后面我們會(huì)講到這個(gè)流程是怎么樣的。
?其次,URI是CP的身份證,唯一標(biāo)識(shí)。
?我們?cè)贏pp1中為CP聲明URI,也就是authorities的值為baobao,那么在App2中想使用它,就在ContentResolver的增刪改查4個(gè)方法中指定URI,格式為:
?uri = Uri.parse("content://baobao/");
?接下來(lái)把兩個(gè)App都進(jìn)入debug模式,就可以從App2調(diào)試進(jìn)入App1了,比如說(shuō),query操作。
?(2)CP的本質(zhì)
?CP的本質(zhì)是把數(shù)據(jù)存儲(chǔ)在SQLite數(shù)據(jù)庫(kù)中。
?各種數(shù)據(jù)源,有各種格式,比如短信、通信錄,它們?cè)赟QLite中就是不同的數(shù)據(jù)表,但是對(duì)外界的使用者而言,就需要封裝成統(tǒng)一的訪(fǎng)問(wèn)方式,比如說(shuō)對(duì)于數(shù)據(jù)集合而言,必須要提供增刪改查四個(gè)方法,于是我們?cè)赟QLite之上封裝了一層,也就是CP。
?(3)匿名共享內(nèi)存(ASM)
?CP讀取數(shù)據(jù)使用到了匿名共享內(nèi)存,英文簡(jiǎn)稱(chēng)ASM,所以你看上面CP和AMS通信忙的不亦樂(lè)乎,其實(shí)下面別有一番風(fēng)景。
?關(guān)于ASM的概念,它其實(shí)也是個(gè)Binder通信,我畫(huà)個(gè)圖哦,你們就明白了:
?什么?還沒(méi)看懂?那我再畫(huà)一個(gè)類(lèi)的交互關(guān)系圖:
?這里的CursorWindow就是匿名共享內(nèi)存。
?這個(gè)流程,簡(jiǎn)單來(lái)說(shuō)是這樣的:
?1)Client內(nèi)部有一個(gè)CursorWindow對(duì)象,發(fā)送請(qǐng)求的時(shí)候,把這個(gè)CursorWindow類(lèi)型的對(duì)象傳過(guò)去,這個(gè)對(duì)象暫時(shí)為空。
?2)Server收到請(qǐng)求,搜集數(shù)據(jù),填充到這個(gè)CursorWindow對(duì)象。
? 3)Client讀取內(nèi)部的這個(gè)CursorWindow對(duì)象,獲取到數(shù)據(jù)。
?由此可見(jiàn),這個(gè)CursorWindow對(duì)象,就是匿名共享內(nèi)存,這是同一塊匿名內(nèi)存。
?舉個(gè)生活中的例子就是,你定牛奶,在你家門(mén)口放個(gè)箱子,送牛奶的人每天早上往這個(gè)箱子放一袋牛奶,你睡醒了去箱子里取牛奶。這個(gè)牛奶箱就是匿名共享內(nèi)存。
?(4)CP與AMS的通信流程
?接下來(lái)我們看一下CP是怎么和AMS通信的。
?能堅(jiān)持看到這里的人,都不容易。我努力多貼圖,不貼代碼,即使有代碼,也是App開(kāi)發(fā)人員能看懂的代碼。
?還是拿App2想訪(fǎng)問(wèn)App1中定義的CP為例子。我們就看CP的insert方法。
?上面這5行代碼,包括了啟動(dòng)CP和執(zhí)行CP方法兩部分,分水嶺在insert方法,insert方法的實(shí)現(xiàn),前半部分仍然是在啟動(dòng)CP,當(dāng)CP啟動(dòng)后獲取到CP的代理對(duì)象,后半部分是通過(guò)代理對(duì)象,調(diào)用insert方法。
?整體的流程如下圖所示:
?1)App2發(fā)送消息給AMS,想要訪(fǎng)問(wèn)App1中的CP。
?2)AMS檢查發(fā)現(xiàn),App1中的CP沒(méi)啟動(dòng)過(guò),為此新開(kāi)一個(gè)進(jìn)程,啟動(dòng)App1,然后獲取到App1啟動(dòng)的CP,把CP的代理對(duì)象返回給App2。
?3)App2拿到CP的代理對(duì)象,也就是IContentProvider,就調(diào)用它的增刪改查4個(gè)方法了,接下來(lái)就是使用ASM來(lái)傳輸數(shù)據(jù)或者修改數(shù)據(jù)了,也就是上面提到的CursorWindow這個(gè)類(lèi),取得數(shù)據(jù)或者操作結(jié)果即可,作為App的開(kāi)發(fā)人員,不需要知道太多底層的詳細(xì)信息,用不上。
?至此,關(guān)于CP的介紹就結(jié)束了。下一篇文章,我們看一下App的安裝流程,也就PMS。