ContentProvider的知識

四大組件之一的ContentProvider兽掰,主要用于在不同的應(yīng)用程序之間實現(xiàn)數(shù)據(jù)的共享么翰。誤區(qū):ContentProvider實際并不存儲數(shù)據(jù)族吻,實際存儲是在SQLite、SharePreferences或文件等地姐浮,它只是對外提供了統(tǒng)一的讀寫接口谷遂。

本想著內(nèi)容為ContentProvider的使用和源碼分析,但發(fā)現(xiàn)本人水平有限源碼分析變成了源碼追蹤单料,本文作為個人的筆記埋凯,源碼部分還請掠過

簡單使用

1点楼、實現(xiàn)ContentProvider,完成數(shù)據(jù)實際的增刪改查操作

/**
 * Created by mr.lin on 2018/5/30.
 * 實際的存儲方式為SQLite
 * MyContentProvider
 */
class MyContentProvider : ContentProvider() {

    companion object {
        val AUTHORITY = "com.ljf.contentprovider.MyContentProvider"http://授權(quán)信息
        val TABLE_USER = 1//路徑碼  此例為哪張表
        val TABLE_ANIMAL = 2
    }

    lateinit var dbHelper: SQLiteOpenHelper
    lateinit var db: SQLiteDatabase
    lateinit var match: UriMatcher

    override fun insert(uri: Uri, values: ContentValues?): Uri {
        db.insert(getTableName(uri), null, values)
        return uri
    }

    override fun query(uri: Uri, projection: Array<out String>?, selection: String?, selectionArgs: Array<out String>?, sortOrder: String?): Cursor {
        return db.query(getTableName(uri), projection, selection, selectionArgs, null, null, sortOrder)
    }

    override fun onCreate(): Boolean {//回調(diào)在Application的onCreate之前
        dbHelper = OpenHelper(context)
        db = dbHelper.writableDatabase
        match = UriMatcher(NO_MATCH)//配置匹配路徑
        match.addURI(AUTHORITY, "user", TABLE_USER)
        match.addURI(AUTHORITY, "animal", TABLE_ANIMAL)
        return true
    }

    override fun update(uri: Uri, values: ContentValues?, selection: String?, selectionArgs: Array<out String>?): Int {
        return db.update(getTableName(uri), values, selection, selectionArgs)
    }

    override fun delete(uri: Uri, selection: String?, selectionArgs: Array<out String>?): Int {
        return db.delete(getTableName(uri), selection, selectionArgs)
    }

    override fun getType(uri: Uri?): String {
        return ""
    }

    private fun getTableName(uri: Uri): String {
        when (match.match(uri)) {//根據(jù)uri匹配路徑
            TABLE_USER -> return "User"
            TABLE_ANIMAL -> return "Animal"
        }
        return ""
    }
}

2白对、注冊

        <provider
            android:name=".MyContentProvider"
            android:authorities="com.ljf.contentprovider.MyContentProvider"http://授權(quán)信息
            android:exported="true"http://是否對外開放
            android:permission="com.ljf.app"http://自定義權(quán)限 />

3掠廓、使用

插入為例
var uri = Uri.parse("content://com.ljf.contentprovider.MyContentProvider/user")
                var value = ContentValues()
                value.put("name", Et1.text.toString())
                value.put("age", Et2.text.toString())
                resultTv.text = contentResolver.insert(uri, value).toString()

完整代碼GitHub

源碼分析

分析的思路是根據(jù)實際使用的流程展開

第一步

通常在Activity獲取ContentResolver,但getContentResolver()在Activity源碼中并未找到甩恼,向父類ContextThemeWrapper尋找


Activity

然而ContextThemeWrapper中也沒有蟀瞧,繼續(xù)向上到ContextWrapper


ContextThemeWrapper

在ContextWrapper中由mBase返回,mBase是ContextImpl的對象


ContextWrapper

在ContextImpl中直接返回成員變量


ContextImpl

發(fā)現(xiàn)mContentResolver在ContextImpl的構(gòu)造方法中初始化条摸,為ApplicationContentResolver的對象


mContentResolver

ApplicationContentResolver又繼承自ContentResolver


ApplicationContentResolver

找到ContentResolver發(fā)現(xiàn)其為抽象類


ContentResolver

第二步

找到了具體的類悦污,實際操作又是如何的?

ApplicationContentResolver為ContextImpl的內(nèi)部類钉蒲,但此類并沒有實現(xiàn)增刪改查操作


ApplicationContentResolver

其父類切端,為抽象類


ContentResolver

插入的實際操作


insert

代碼中實際操作的對象顯示為IContentProvider


IContentProvider

但其為interface,它就是另一進程的ContentProvider

第三步

ContentProvider從哪里來的
返回去看具體實現(xiàn)此接口的對象是由acquireProvider方法返回的


acquireProvider

這里有個重載


重載

返回子類ApplicationContentResolver顷啼,查看具體的實現(xiàn)


發(fā)現(xiàn)調(diào)用了ActivityThread的方法踏枣,這里有兩個分支,一個取緩存(緩存一詞可能不準確)钙蒙、一個創(chuàng)建


ActivityThread

第三步 — 緩存分支

取出value茵瀑,如果發(fā)現(xiàn)Provider的進程已經(jīng)死了handleUnstableProviderDiedLocked,否則增加此provider的計數(shù)incProviderRefLocked


acquireExistingProvider

移除本地的緩存provider躬厌,通知AMS此provider的進程已死


handleUnstableProviderDiedLocked

第三步 — 取AMS中provider

ActivityManagerNative.getDefault()即為AMS


getContentProvider

關(guān)鍵的方法getContentProviderImpl马昨,由于水平有限并不能解析源碼,只知道通過IPC啟動另一進程中的ContentProvider并返回扛施。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末鸿捧,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子疙渣,更是在濱河造成了極大的恐慌笛谦,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,039評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件昌阿,死亡現(xiàn)場離奇詭異,居然都是意外死亡恳邀,警方通過查閱死者的電腦和手機懦冰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來谣沸,“玉大人刷钢,你說我怎么就攤上這事∪楦剑” “怎么了内地?”我有些...
    開封第一講書人閱讀 165,417評論 0 356
  • 文/不壞的土叔 我叫張陵伴澄,是天一觀的道長。 經(jīng)常有香客問我阱缓,道長非凌,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,868評論 1 295
  • 正文 為了忘掉前任荆针,我火速辦了婚禮敞嗡,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘航背。我一直安慰自己喉悴,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,892評論 6 392
  • 文/花漫 我一把揭開白布玖媚。 她就那樣靜靜地躺著箕肃,像睡著了一般。 火紅的嫁衣襯著肌膚如雪今魔。 梳的紋絲不亂的頭發(fā)上勺像,一...
    開封第一講書人閱讀 51,692評論 1 305
  • 那天,我揣著相機與錄音涡贱,去河邊找鬼咏删。 笑死,一個胖子當(dāng)著我的面吹牛问词,可吹牛的內(nèi)容都是我干的督函。 我是一名探鬼主播,決...
    沈念sama閱讀 40,416評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼激挪,長吁一口氣:“原來是場噩夢啊……” “哼辰狡!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起垄分,我...
    開封第一講書人閱讀 39,326評論 0 276
  • 序言:老撾萬榮一對情侶失蹤宛篇,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后薄湿,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體叫倍,經(jīng)...
    沈念sama閱讀 45,782評論 1 316
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,957評論 3 337
  • 正文 我和宋清朗相戀三年豺瘤,在試婚紗的時候發(fā)現(xiàn)自己被綠了吆倦。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,102評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡坐求,死狀恐怖蚕泽,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情桥嗤,我是刑警寧澤须妻,帶...
    沈念sama閱讀 35,790評論 5 346
  • 正文 年R本政府宣布仔蝌,位于F島的核電站,受9級特大地震影響荒吏,放射性物質(zhì)發(fā)生泄漏敛惊。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,442評論 3 331
  • 文/蒙蒙 一司倚、第九天 我趴在偏房一處隱蔽的房頂上張望豆混。 院中可真熱鬧,春花似錦动知、人聲如沸皿伺。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽鸵鸥。三九已至,卻和暖如春丹皱,著一層夾襖步出監(jiān)牢的瞬間妒穴,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評論 1 272
  • 我被黑心中介騙來泰國打工摊崭, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留讼油,地道東北人。 一個月前我還...
    沈念sama閱讀 48,332評論 3 373
  • 正文 我出身青樓呢簸,卻偏偏與公主長得像矮台,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子根时,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,044評論 2 355

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