Android 淺析 ContentProvider (一) 使用

Android 淺析 ContentProvider (一) 使用

前言

Linus Benedict Torvalds : RTFSC – Read The Fucking Source Code

概括

Content providers are one of the primary building blocks of Android applications, providing content to applications. They encapsulate data and provide it to applications through the single ContentResolver interface. A content provider is only required if you need to share data between multiple applications. For example, the contacts data is used by multiple applications and must be stored in a content provider. If you don't need to share data amongst multiple applications you can use a database directly via SQLiteDatabase.

我們先來(lái)看一張圖片讓我們對(duì)Content Provider有一個(gè)直觀(guān)的了解:


Content Provider

ContentProvider提供了在應(yīng)用程序之前共享數(shù)據(jù)的一種機(jī)制。
1、存儲(chǔ)和獲取數(shù)據(jù)提供了統(tǒng)一的接口至耻。
2破加、對(duì)數(shù)據(jù)進(jìn)行封裝剧防,不用關(guān)心數(shù)據(jù)存儲(chǔ)的細(xì)節(jié)旦装。
3笛坦、Android為常見(jiàn)的一些數(shù)據(jù)提供了默認(rèn)的ContentProvider(包括音頻狠持、視頻疟位、圖片和通訊錄等)。
最主要的是ContentProvider對(duì)外共享數(shù)據(jù)統(tǒng)一了數(shù)據(jù)的訪(fǎng)問(wèn)方式喘垂。

組件使用

首先來(lái)看下如何實(shí)現(xiàn)一個(gè)ContentProvider功能:

功能簡(jiǎn)述

服務(wù)端:
有六個(gè)最主要的方法需要重寫(xiě):
1甜刻、onCreate() which is called to initialize the provider.
2、query(Uri, String[], String, String[], String) which returns data to the caller.
3正勒、insert(Uri, ContentValues) which inserts new data into the content provider.
4罢吃、update(Uri, ContentValues, String, String[]) which updates existing data in the content provider.
5、delete(Uri, String, String[]) which deletes data from the content provider.
6昭齐、getType(Uri) which returns the MIME type of data in the content provider.
注意:
insert()和update()方法有可能被多線(xiàn)程調(diào)用尿招,一定要是線(xiàn)程安全的。
onCreate()方法只會(huì)調(diào)用一次阱驾,但要避免冗長(zhǎng)的操作就谜。

客戶(hù)端:
通過(guò)ContentResolver可以自動(dòng)獲取Provider的實(shí)例,不必?fù)?dān)心跨進(jìn)程調(diào)用的細(xì)節(jié)里覆。

代碼例子

服務(wù)端:
AndroidManifest.xml

<!-- android:exported="true" 指示該服務(wù)是否能夠被其他應(yīng)用程序組件調(diào)用或跟它交互丧荐。 -->
<provider
    android:name="com.unknow.jason.testdatabaseex.DatabaseProvider"
    android:authorities="com.unknow.jason.testdatabaseex.provider"
    android:exported="true"
    android:enabled="true" >
</provider>

淺析:
AndroidManifest添加provider服務(wù),在安裝App的時(shí)候會(huì)自動(dòng)注冊(cè)這個(gè)Provider服務(wù)到AMS里作備份喧枷,這個(gè)服務(wù)最關(guān)鍵的點(diǎn)是authorities虹统,作為Provider唯一標(biāo)識(shí),讓其它程序可以在A(yíng)MS里面查詢(xún)到此Provider服務(wù)隧甚。
ps.更多關(guān)于Provider的權(quán)限可以看http://developer.android.com/guide/topics/manifest/provider-element.html车荔。

DatabaseProvider.java

public class DatabaseProvider extends ContentProvider {
    @Override
    public boolean onCreate() {
        return true;
    }
    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
                        String sortOrder) {
        return null;
    }
    @Override
    public Uri insert(Uri uri, ContentValues values) {
        return null;
    }
    @Override
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
        return 0;
    }
    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        return 0;
    }
    @Override
    public String getType(Uri uri) {
        return null;
    }
}

淺析:
Provider最主要的六個(gè)方法。
getType():
Implement this to handle requests for the MIME type of the data at the given URI. The returned MIME type should start with vnd.android.cursor.item for a single record, or vnd.android.cursor.dir/ for multiple items.
注意: 這方法有可能用于多線(xiàn)程戚扳。用于訪(fǎng)問(wèn)此信息的應(yīng)用程序不需要權(quán)限忧便;如果您的內(nèi)容提供者需要讀和/或?qū)憴?quán)限,或不導(dǎo)出帽借,所有應(yīng)用程序都可以調(diào)用此方法珠增,不管其訪(fǎng)問(wèn)權(quán)限超歌。這使他們能夠檢索URI的MIME類(lèi)型時(shí),調(diào)度意圖蒂教。

insert():
Implement this to handle requests to insert a new row. As a courtesy, call notifyChange() after inserting.
注意: 這方法有可能用于多線(xiàn)程巍举。

onCreate():
Implement this to initialize your content provider on startup. This method is called for all registered content providers on the application main thread at application launch time. It must not perform lengthy operations, or application startup will be delayed.
注意: 如果你使用SQLite進(jìn)行數(shù)據(jù)庫(kù)操作,切勿在此方法中調(diào)用getReadableDatabase() or getWritableDatabase()方法凝垛,作為代替禀综,可以使用onOpen(SQLiteDatabase)作為第一次初始數(shù)據(jù)庫(kù)。

query():
Implement this to handle query requests from clients.
注意: 這方法有可能用于多線(xiàn)程苔严。

delete():
Implement this to handle requests to delete one or more rows. The implementation should apply the selection clause when performing deletion, allowing the operation to affect multiple rows in a directory. As a courtesy, call notifyChange() after deleting.
注意: 這方法有可能用于多線(xiàn)程。如果一個(gè)特定的行要被刪除孤澎,它會(huì)在URI的末尾解析出這一行的ID届氢。

update():
Implement this to handle requests to update one or more rows. The implementation should update all rows matching the selection to set the columns according to the provided values map. As a courtesy, call notifyChange() after updating.
注意: 這方法有可能用于多線(xiàn)程。

sqlhelper.java

public class SqlHelper extends SQLiteOpenHelper {
    public static final String CREATE_BOOK = "create table Book ("
            + "id integer primary key autoincrement, "
            + "author text, "
            + "price real, "
            + "pages integer, "
            + "name text)";

    public static final String CREATE_CATEGORY = "create table Category ("
            + "id integer primary key autoincrement, "
            + "category_name text)";

    public SqlHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(CREATE_BOOK);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("drop table if exists Book");
        onCreate(db);
    }
}

客戶(hù)端:

Uri uri = Uri.parse("content://com.unknow.jason.testdatabaseex.provider/book");
Cursor cursor = getContentResolver().query(uri, null, null, null, null);

if (cursor != null) {
    while (cursor.moveToNext()) {
        String name = cursor.getString(cursor.getColumnIndex("name"));
    }
}

淺析:
getContentResolver().query():
Query the given URI, returning a Cursor over the result set with optional support for cancellation.
為了更佳的性能覆旭,調(diào)用者應(yīng)該遵循兩點(diǎn):
1退子、提供一個(gè)明確的projection,防止從存儲(chǔ)中讀取不需要的數(shù)據(jù)型将。
2寂祥、使用問(wèn)號(hào)參數(shù)標(biāo)記,如“電話(huà)=七兜?”而不是在選擇參數(shù)中的顯式值丸凭,因此,不同的值的查詢(xún)將被確認(rèn)為緩存的目的相同的腕铸。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末惜犀,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子狠裹,更是在濱河造成了極大的恐慌虽界,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,734評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件涛菠,死亡現(xiàn)場(chǎng)離奇詭異莉御,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)俗冻,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén)礁叔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人迄薄,你說(shuō)我怎么就攤上這事晴圾。” “怎么了噪奄?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,133評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵死姚,是天一觀(guān)的道長(zhǎng)人乓。 經(jīng)常有香客問(wèn)我,道長(zhǎng)都毒,這世上最難降的妖魔是什么色罚? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,532評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮账劲,結(jié)果婚禮上戳护,老公的妹妹穿的比我還像新娘。我一直安慰自己瀑焦,他們只是感情好腌且,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,585評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著榛瓮,像睡著了一般铺董。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上禀晓,一...
    開(kāi)封第一講書(shū)人閱讀 51,462評(píng)論 1 302
  • 那天精续,我揣著相機(jī)與錄音,去河邊找鬼粹懒。 笑死重付,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的凫乖。 我是一名探鬼主播确垫,決...
    沈念sama閱讀 40,262評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼帽芽!你這毒婦竟也來(lái)了森爽?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,153評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤嚣镜,失蹤者是張志新(化名)和其女友劉穎爬迟,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體菊匿,經(jīng)...
    沈念sama閱讀 45,587評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡付呕,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,792評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了跌捆。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片徽职。...
    茶點(diǎn)故事閱讀 39,919評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖佩厚,靈堂內(nèi)的尸體忽然破棺而出姆钉,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 35,635評(píng)論 5 345
  • 正文 年R本政府宣布潮瓶,位于F島的核電站陶冷,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏毯辅。R本人自食惡果不足惜埂伦,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,237評(píng)論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望思恐。 院中可真熱鬧沾谜,春花似錦、人聲如沸胀莹。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,855評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)描焰。三九已至媳否,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間栈顷,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,983評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工嵌巷, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留萄凤,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,048評(píng)論 3 370
  • 正文 我出身青樓搪哪,卻偏偏與公主長(zhǎng)得像靡努,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子晓折,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,864評(píng)論 2 354

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

  • Correctness AdapterViewChildren Summary: AdapterViews can...
    MarcusMa閱讀 8,864評(píng)論 0 6
  • PLEASE READ THE FOLLOWING APPLE DEVELOPER PROGRAM LICENSE...
    念念不忘的閱讀 13,471評(píng)論 5 6
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理惑朦,服務(wù)發(fā)現(xiàn),斷路器漓概,智...
    卡卡羅2017閱讀 134,656評(píng)論 18 139
  • afinalAfinal是一個(gè)android的ioc漾月,orm框架 https://github.com/yangf...
    passiontim閱讀 15,429評(píng)論 2 45
  • 很久沒(méi)下筆了,嗯胃珍,可以說(shuō)梁肿,從高考以后,就沒(méi)有提筆寫(xiě)過(guò)文章觅彰。 上大學(xué)后一直混混然不覺(jué)得有什么不好吩蔑,直到六級(jí)考試寫(xiě)作文...
    AMBER_li閱讀 133評(píng)論 0 1