Day 30 | ContentProvider

可以使用ContentProvider将资料库分享给其他应用程序共享资讯,或从其他应用程序操作资料

ContentProvider分为Provider(提供者)与Resolver(解析者)两个角色,Provider定义授权的名称并提供内容让Resolver操作,Resolver则向特定授权名称的Provider要求内容操作。

应用程序会以特定格式的Uri类别表示,开发者透过授权名称(Authority)访问其他应用程序的内容

Untitled

  • Scheme为前缀字,在ContentProvider都用content://
  • Authority为自定义的授权名称,用於识别内容来源
  • Path为内容路径,用於区分不同资料的存取,可不填
  • ID为内容的为一识别标签,可将资料库中每笔纪录建立独立的Uri

建立ContentProvider

  1. File→New→Other→Content Provider

    Untitled

  2. 修改名称与授权名称後点Finish

    Untitled

  3. AS会自动产生ContentProvider需要的档案,AndroidManifest.xml也会自动增加Receiver的资讯

    Untitled

提供与解析ContentProvider

实作Provider

class MyContentProvider : ContentProvider() {
    private lateinit var dbrw: SQLiteDatabase

    //Step1:当Resolver要求操作资料时,Provider会先进入onCreate(),需先开启资料库
    override fun onCreate(): Boolean {
        val context = context ?: return false
        //取得资料库实体
        dbrw = MyDBHelper(context).writableDatabase
        return true
    }

    //Step2:Resolver要求新增资料,则取得它给予的资料并新增於资料库
    override fun insert(uri: Uri, values: ContentValues?): Uri? {
        //取出其他应用程序给予的book资料
        val book = values ?: return null
        //将资料薪曾於资料库病回传此笔纪录的ID
        val rowID = dbrw.insert("myTable", null, book)
        //回传此笔纪录的Uri
        return Uri.parse("content://com.italkutalk.lab16/book/$rowID")
    }

    override fun update(
        uri: Uri, values: ContentValues?, selection: String?,
        selectionArgs: Array<String>?
    ): Int = 0
    
    override fun delete(uri: Uri, selection: String?, selectionArgs: Array<String>?): Int = 0

    override fun getType(uri: Uri): String? = null

    override fun query(
        uri: Uri, projection: Array<String>?, selection: String?,
        selectionArgs: Array<String>?, sortOrder: String?
    ): Cursor? = null

}

实作Resolver

Provider完成後,需建立另一个应用程序作为Resolver,Resolver需在AndroidManifest.xml定义Provider的package名称。

Untitled

<queries>
        <package android:name="com.italkutalk.lab16"/>
</queries>

接着撰写程序码,实作Resolver以新增资料

//Step1:建立ContentValues物件,用於存放要新增的资料
val values = ContentValues()
//book栏位填入恐龙书
values.put("book", "恐龙书")
//price栏位填入1400
values.put("price", 1400)
//Step2:透过insert()放入Uri及ContentValues让provider新增资料
val uri = Uri.parse("content://com.italkutalk.lab16")
val contentUri = contentResolver.insert(uri, values)
//Step3:判断回传此笔纪录Uri是否为null,以确认资料新增是否成功
if (contentUri != null)
    Toast.makeText(this, "新增:恐龙书,价格:1400",Toast.LENGTH_LONG).show()
else
    Toast.makeText(this, "新增失败",Toast.LENGTH_LONG).show()

<<:  Day 18 一切都不是理所当然的!

>>:  【Day 15】从零开始的 Debug 生活 - Debugger 原理

用React刻自己的投资Dashboard Day30 - 股票代号输入防呆机制

tags: 2021铁人赛 React 股票代号输入错误当机问题 Day28的文章有提到,当使用者想...

[Day 28] banana in a box!关於双向系结功能的语法糖

Okay!最後几天要看的内容是关於 Angular 的双向系结。 如果你跟我一样是从 Angular...

小产品跟大产品都可以通用的决策系统:Randomized AB Test

疫苗在台湾第一次吵得沸沸扬扬时,我也被各种有孔没笋的消息搞得莫名其妙,为了跟人争辩时不要说错话,闲人...

OpenID Connect

OAuth 2.0 指定了存取资源的存取令牌,但它没有提供提供身份信息(ID Token)的标准方...

30天学会C语言: Day 13-递回体验镇魂曲

递回 在函式里面可以呼叫函式本身 下面例子中,fun() 会先将参数 x 显示到视窗上,之後判断 x...