?(十二)ContentProvider
?(1)ContentProvider是什么?
? ContentProvider栽连,簡稱CP险领。
?做App開發(fā)的同學(xué),尤其是電商類App秒紧,對CP并不熟悉绢陌,對這個概念的最大程度的了解,也僅僅是建立在書本上噩茄,它是Android四大組件中的一個下面。
?做系統(tǒng)管理類的App,比如說手機(jī)助手這種绩聘,有機(jī)會頻繁使用CP沥割。
?而對于應(yīng)用類App耗啦,數(shù)據(jù)通常存在服務(wù)器端,其它應(yīng)用類App也想使用的時候机杜,一般都是從服務(wù)器取數(shù)據(jù)帜讲,所以沒機(jī)會使用到CP。
?有時候我們會在自己的App中讀取通信錄或者短信的數(shù)據(jù)椒拗,這時候就需要用到CP了似将。通信錄或者短信的數(shù)據(jù),是以CP的形式提供的蚀苛,我們在App這邊在验,是使用方。
?對于做應(yīng)用類App的同學(xué)堵未,很少有機(jī)會自定義CP供其它App使用腋舌。
?我們快速回顧一下在App中怎么使用CP。
?1)定義CP的App1:
?在App1中定義一個CP的子類MyContentProvider渗蟹,并在Manifest中聲明块饺,為此要在MyContentProvider中實現(xiàn)CP的增刪改查四個方法:
?2)使用CP的App2:
?在App2訪問App1中定義的CP,為此雌芽,要使用到ContentResolver授艰,它也提供了增刪改查4個方法,用于訪問App1中定義的CP:
?首先我們看一下ContentResolver的增刪改查這4個方法的底層實現(xiàn)世落,其實都是和AMS通信淮腾,最終調(diào)用App1的CP的增刪改查4個方法,后面我們會講到這個流程是怎么樣的岛心。
?其次来破,URI是CP的身份證篮灼,唯一標(biāo)識忘古。
?我們在App1中為CP聲明URI,也就是authorities的值為baobao诅诱,那么在App2中想使用它髓堪,就在ContentResolver的增刪改查4個方法中指定URI,格式為:
?uri = Uri.parse("content://baobao/");
?接下來把兩個App都進(jìn)入debug模式娘荡,就可以從App2調(diào)試進(jìn)入App1了干旁,比如說,query操作炮沐。
?(2)CP的本質(zhì)
?CP的本質(zhì)是把數(shù)據(jù)存儲在SQLite數(shù)據(jù)庫中争群。
?各種數(shù)據(jù)源,有各種格式大年,比如短信换薄、通信錄玉雾,它們在SQLite中就是不同的數(shù)據(jù)表,但是對外界的使用者而言轻要,就需要封裝成統(tǒng)一的訪問方式复旬,比如說對于數(shù)據(jù)集合而言,必須要提供增刪改查四個方法冲泥,于是我們在SQLite之上封裝了一層驹碍,也就是CP。
?(3)匿名共享內(nèi)存(ASM)
?CP讀取數(shù)據(jù)使用到了匿名共享內(nèi)存凡恍,英文簡稱ASM志秃,所以你看上面CP和AMS通信忙的不亦樂乎,其實下面別有一番風(fēng)景嚼酝。
?關(guān)于ASM的概念洽损,它其實也是個Binder通信,我畫個圖哦革半,你們就明白了:
?什么碑定?還沒看懂?那我再畫一個類的交互關(guān)系圖:
?這里的CursorWindow就是匿名共享內(nèi)存又官。
?這個流程延刘,簡單來說是這樣的:
?1)Client內(nèi)部有一個CursorWindow對象,發(fā)送請求的時候六敬,把這個CursorWindow類型的對象傳過去碘赖,這個對象暫時為空。
?2)Server收到請求外构,搜集數(shù)據(jù)普泡,填充到這個CursorWindow對象。
? 3)Client讀取內(nèi)部的這個CursorWindow對象审编,獲取到數(shù)據(jù)撼班。
?由此可見,這個CursorWindow對象垒酬,就是匿名共享內(nèi)存砰嘁,這是同一塊匿名內(nèi)存褐桌。
?舉個生活中的例子就是屈尼,你定牛奶,在你家門口放個箱子醋寝,送牛奶的人每天早上往這個箱子放一袋牛奶口糕,你睡醒了去箱子里取牛奶缅阳。這個牛奶箱就是匿名共享內(nèi)存。
?(4)CP與AMS的通信流程
?接下來我們看一下CP是怎么和AMS通信的景描。
?能堅持看到這里的人十办,都不容易孤里。我努力多貼圖,不貼代碼橘洞,即使有代碼捌袜,也是App開發(fā)人員能看懂的代碼。
?還是拿App2想訪問App1中定義的CP為例子炸枣。我們就看CP的insert方法虏等。
?上面這5行代碼,包括了啟動CP和執(zhí)行CP方法兩部分适肠,分水嶺在insert方法霍衫,insert方法的實現(xiàn),前半部分仍然是在啟動CP侯养,當(dāng)CP啟動后獲取到CP的代理對象敦跌,后半部分是通過代理對象,調(diào)用insert方法逛揩。
?整體的流程如下圖所示:
?1)App2發(fā)送消息給AMS柠傍,想要訪問App1中的CP。
?2)AMS檢查發(fā)現(xiàn)辩稽,App1中的CP沒啟動過惧笛,為此新開一個進(jìn)程,啟動App1逞泄,然后獲取到App1啟動的CP患整,把CP的代理對象返回給App2。
?3)App2拿到CP的代理對象喷众,也就是IContentProvider各谚,就調(diào)用它的增刪改查4個方法了,接下來就是使用ASM來傳輸數(shù)據(jù)或者修改數(shù)據(jù)了到千,也就是上面提到的CursorWindow這個類昌渤,取得數(shù)據(jù)或者操作結(jié)果即可,作為App的開發(fā)人員父阻,不需要知道太多底層的詳細(xì)信息愈涩,用不上望抽。
?至此加矛,關(guān)于CP的介紹就結(jié)束了。下一篇文章煤篙,我們看一下App的安裝流程斟览,也就PMS。