1.什么是內容提供者?
?? ? 首先在android 開發(fā)藝術探索這邊書中 我們都知道ContentProvider(內容提供者)是android中的四大組件之一略荡,但是在一般的開發(fā)中,可能使用比較少蹬叭。ContentProvider為不同的軟件之間數(shù)據(jù)共享乡摹,提供統(tǒng)一的接口。而且ContentProvider是以類似數(shù)據(jù)庫中表的方式將數(shù)據(jù)暴露缩赛,也就是說ContentProvider就像一個“數(shù)據(jù)庫”耙箍。那么外界獲取其提供的數(shù)據(jù),也就應該與從數(shù)據(jù)庫中獲取數(shù)據(jù)的操作基本一樣酥馍,只不過是采用URI來表示外界需要訪問的“數(shù)據(jù)庫”辩昆。至于如何從URI中識別出外界需要的是哪個“數(shù)據(jù)庫”這就是Android底層需要做的事情了,也就是說旨袒,如果我們想讓其他的應用使用我們自己程序內的數(shù)據(jù)汁针,就可以使用ContentProvider定義一個對外開放的接口,從而使得其他的應用可以使用我們自己應用中的文件砚尽、數(shù)據(jù)庫內存儲的信息施无。當然,自己開發(fā)的應用需要給其他應用共享信息的需求可能比較少見必孤,但是在Android系統(tǒng)中猾骡,很多數(shù)據(jù)如:聯(lián)系人信息、短信信息敷搪、圖片庫兴想、音頻庫等,這些信息在開發(fā)中還是經(jīng)常用到的购啄,這些信息谷歌工程師已經(jīng)幫我們封裝好了襟企,我們可以使用谷歌給我的Uri去直接訪問這些數(shù)據(jù)。所以對于ContentProvider我們還是需要認真的學習的狮含,在遇到獲取聯(lián)系人信息顽悼,圖片庫,音視頻庫等需求的時候几迄,才能更好的實現(xiàn)功能蔚龙。
2.為什么會有內容提供者?
? ? ? ?當應用繼承ContentProvider類映胁,并重寫該類用于提供數(shù)據(jù)和存儲數(shù)據(jù)的方法木羹,就可以向其他應用共享其數(shù)據(jù)。雖然使用其他方法也可以對外共享數(shù)據(jù),但數(shù)據(jù)訪問方式會因數(shù)據(jù)存儲的方式而不同坑填,如:采用文件方式對外共享數(shù)據(jù)抛人,需要進行文件操作讀寫數(shù)據(jù);采用sharedpreferences共享數(shù)據(jù)脐瑰,需要使用sharedpreferences API讀寫數(shù)據(jù)妖枚。而使用ContentProvider共享數(shù)據(jù)的好處是統(tǒng)一了數(shù)據(jù)訪問方式,這也是為什么會有內容提供者的原因苍在。
在這里解釋一下:怎么理解ContentProvider統(tǒng)一了數(shù)據(jù)訪問方式
根據(jù)官網(wǎng)上的描述绝页,content?provider主要是提供應用程序之間的數(shù)據(jù)共享。比如App A?需要App B的數(shù)據(jù)能用shared?preference寂恬?用文件的話续誉,還只能用external?file,但是可能沒有外存初肉,文件可能會被刪除酷鸦,權限問題等等。所以content?provider+content?resolver是最好的方式朴译。
而且記住井佑,content?provider+content?resolver只是提供了應用程序之間的一個通道,具體的數(shù)據(jù)處理是在content?provider中眠寿,contetn provider 對底層的數(shù)據(jù)存儲方法沒有任何的要求 有可能是文件躬翁,可能是sqlite怒见,也有可能是采用內存中的一個對象來進行數(shù)據(jù)存儲印颤。
3.應該怎么實現(xiàn)自己的ContentProvider?
下面是一個簡單的實列 他演示了ContentProvider的工作過程 首先是創(chuàng)建一個MyContentProvider類 ,它繼承ContentProvider并實現(xiàn)了ContentProvider的六個必須要實現(xiàn)的方法 ?在下面代碼中 我們什么都么有干 盡管如此 ?這個MyContentProvider 也是可以工作的 ?只是它無法向外界提供有效的數(shù)據(jù)而已
然后接著我們需要在功能清單中Manifest中注冊 MyContentProvider 如下圖所示 其中 android:authorities="star.liuwen.com.endcontentprovider.MyContentProvider" 是ContentProvider中的唯一標識 ?而process 則是獨立進程的標志 ?
然后我們可以看到打印出來的日志
從日志中我們可以看到MyContentProvider 中的query方法被調用了三次 并且三次都是在不同的線程當中 ?可以看出來 ?他們都是運行在一個BInder線程當中 ?而onCreate()方法則是在主線程當中 ?也就是我們的UI線程
到這里 我們自定義的MyContentProvider 已經(jīng)跑通了 雖然MyContentProvider 中沒有返回任何的數(shù)據(jù) 所以接下來 我們繼續(xù)完善 需要MyContentProvider 能夠對外提供數(shù)據(jù) 上面我寫了Contetn provider 對底層的數(shù)據(jù)存儲方法沒有任何的要求 可以是文件 也可以是SqLite 這里我們簡單的用SqLite來實現(xiàn)存儲
上面代碼是一個簡單的數(shù)據(jù)庫實現(xiàn) 我們借助SqLiteHelper 來管理數(shù)據(jù)可的創(chuàng)建 支持 和升級 下面我們就要通過MyContentProvider向外界提供數(shù)據(jù)庫中的信息 ?我們知道 ContentProvider 是通過Uri 來區(qū)分外界要訪問的數(shù)據(jù)集合 在本列中支持外界對MyContentProvider 中的book表 和user表進行訪問 為了知道外界要訪問的是哪個表 我們需要為他們定義單獨的Uri 和Uri_code 并將Uri和Uri_code 相關聯(lián) 我們可以使用UriMatcher的addUrI方法將Uri_code關聯(lián)到一起 這樣 當外界請求訪問MyContentProvider 時玛迄,我們就可以根據(jù)請求的Uri來得到Uri_code 有了Uri_code 我們就可以知道外界想要訪問哪個表 然后就可以進行相應的數(shù)據(jù)操作了?
完整代碼就是這樣的?
下面在看Activity中的 代碼
我這里的代碼都是截圖 也是希望大家能自己敲一遍 好 接下來我們看打印的日志是怎樣的