android-第一行代码-第七章 内容提供器Content provider(温故而知新-含Demo版)学习记录

第七章 内容提供器

首先是阅读《第一行代码》中关于内容提供器的介绍;之后阅读最新的google官方文档对内容提供器的介绍。

因为《第一行代码》中关于content provider的知识点很多都是围绕之前持久化技术中Sqlite进行入手的。但是这个数据库我是采用的官方文档推荐的Room进行学习认识的;不清楚的小伙伴可以回顾持久化技术参考学习。故本章节的学习并不是完全根植于《第一行代码》,更多的依靠官方文档和网络上的相关资料进行学习认识。
【参考资料1】;
也可以直接配合自己些的简易Demo使用!

初看官方文档的思考

终于读完了晦涩难懂的官方文档对content Provider的介绍;英文读起来断断续续的,还得借助一些翻译软件。

  1. 权限permission和这次学习的ContentProvider息息相关;
  2. content Provider对于数据的安全性有较强的控制能力;
  3. content Provider不单单针对向外进行内容提供,而且可以对自己application进行数据的控制。

推荐再阅读一下中文版本的,毕竟以上都是我初步的一个思考,肯定具有一定的局限性的。

如需访问内容提供程序中的数据,您可以客户端的形式使用应用的 Context 中的 ContentResolver 对象与提供程序进行通信。ContentResolver 对象会与提供程序对象(即实现 ContentProvider 的类的实例)通信。

基础知识

访问数据前期准备

  1. 主要是通过URI获取Retrieve数据进行访问;这里的URI和URL的概念容易混淆,不过也蛮好区分的,有点类似”父与子“的关系~

URI,统一资源标志符(Uniform Resource Identifier, URI);URL是URI的一个子集。
它是Uniform Resource Locator的缩写,译为“统一资源定位符”。

以下代码示例是根据自带的UserDictionary进行操作的;不难看出这个Query方法的几个参数的意思是啥,现在不理解也没关系最终肯定要通过一些小的Demo进行学习认识的。

// Queries the user dictionary and returns results
cursor = getContentResolver().query(
    UserDictionary.Words.CONTENT_URI,   // The content URI of the words table
    projection,                        // The columns to return for each row
    selectionClause,                   // Selection criteria
    selectionArgs,                     // Selection criteria
    sortOrder);                        // The sort order for the returned rows

对于指定待检索行的表达式,我们将其拆分为选择子句和选择参数。选择子句是逻辑和布尔表达式、列名称以及值(变量 mSelectionClause)的组合。如果您指定可替换参数 ? 而非值,查询方法会从选择参数数组(变量 mSelectionArgs)中检索值。

一个内容URI的组成由以下部分组成:authority以及path;
如下:where the user_dictionary string is the provider’s authority, and the words string is the table’s path.

content://user_dictionary/words

  1. 访问权限
    这个比较好理解,你向人家获取一些信息啥的你不得问问,请求一下人家的想法吗?难道先上车后补票吗?想的美~
    例如官方文档中是用用户字典为例;所以在manifest清单文件中询问一下android.permission.READ_USER_DICTIONARY权限.
<uses-permission android:name="android.permission.READ_USER_DICTIONARY">

其他注意

  1. 恶意注入
    这个和数据库里的恶意注入其实异曲同工;毕竟这些都是数据的“迁徙”和“奔波”,保护好这些数据义不容辞!

为了避免此问题,请使用将 ? 作为可替换参数的选择子句,以及单独的选择参数数组。执行此操作时,用户输入直接受查询约束,而不不会被解释为 SQL 语句的一部分。由于用户输入未作为 SQL 处理,因此其无法注入恶意 SQL。

这一点在之前的JavaWeb学习中有稍微接触过,虽然很多都不记得了但是基本的逻辑还是没有太多差别的!
以下是官方文档的一个推荐使用手段来避免恶意注入:

// Constructs a selection clause with a replaceable parameter
String selectionClause =  "var = ?";
// Defines an array to contain the selection arguments
String[] selectionArgs = {""};
// Sets the selection argument to the user's input
selectionArgs[0] = userInput;

简单来说就是,占位避免直接进行SQL操作!

整体上正确的避免恶意注入的代码示例如下:依旧从官网上截取的!

/*
 * This defines a one-element String array to contain the selection argument.
 */
String[] selectionArgs = {""};

// Gets a word from the UI
searchString = searchWord.getText().toString();

// Remember to insert code here to check for invalid or malicious input.

// If the word is the empty string, gets everything
if (TextUtils.isEmpty(searchString)) {
    // Setting the selection clause to null will return all words
    selectionClause = null;
    selectionArgs[0] = "";

} else {
    // Constructs a selection clause that matches the word that the user entered.
    selectionClause = UserDictionary.Words.WORD + " = ?";

    // Moves the user's input string to the selection arguments.
    selectionArgs[0] = searchString;

}

// Does a query against the table and returns a Cursor object
mCursor = getContentResolver().query(
    UserDictionary.Words.CONTENT_URI,  // The content URI of the words table
    projection,                       // The columns to return for each row
    selectionClause,                  // Either null, or the word the user entered
    selectionArgs,                    // Either empty, or the string the user entered
    sortOrder);                       // The sort order for the returned rows

// Some providers return null if an error occurs, others throw an exception
if (null == mCursor) {
    /*
     * Insert code here to handle the error. Be sure not to use the cursor! You may want to
     * call android.util.Log.e() to log this error.
     *
     */
// If the Cursor is empty, the provider found no matches
} else if (mCursor.getCount() < 1) {

    /*
     * Insert code here to notify the user that the search was unsuccessful. This isn't necessarily
     * an error. You may want to offer the user the option to insert a new row, or re-type the
     * search term.
     */

} else {
    // Insert code here to do something with the results

}
  1. 分批(批量)处理Batch Access

    批量访问提供程序适用于插入大量行,或通过同一方法调用在多个表中插入行,或者通常用于以事务(原子操作)的形式跨进程边界执行一组操作。

这个概念了解即可,知道这个可以这么用就好;

  1. 协定类ContactClass
    这个是比较重要‼️

协定类可定义一些常量,帮助应用使用内容 URI、列名称、Intent 操作以及内容提供程序的其他功能。提供程序不会自动包含协定类,因此提供程序的开发者需定义这些类,并将其提供给其他开发者。

这个是一个团队里的“辅助”;要想推塔成功,最好不要少了它——这样的Content Provider才完整~

  1. MIME 类型
    这个是一个标准类型表示某个文件是什么类型,例如imge/png,text/html等等。
    不过在这里我们最重要的是认识自定义的MIME类型:
    vnd.android.cursor.dir多行数据类型
    vnd.android.cursor.item单行数据类型
    要是不好理解,看哪个量大就是Dir~

以上是Content Provider一些理论的知识汇总;最终还是要在实践上出真知!
构建一个读取手机中的通讯录信息然后通过List View进行读取展示,完成最基本的一个连接功能!参考资料;

简单思路整理:

  1. ContactsContract是一个通讯信息的协定类,通过这个协定类我们可以实现内容提供器的相应方法,进行相应操作!如Insert和query等等~

  2. ListView的知识回顾主要是Adapter的操作,这个很常用的;当然也可以考虑使用RecyclerView,不过在本章的学习中,这个UI展示不是重点!我们主要是读取信息,展示罢了;重点在Query能否正确获取信息!

  3. 权限获取,这个是必须的!Permission和Content Provider生死与共!很重要的!

  4. 在编写代码的时候,发现还是使用Recycler View吧!我想页面比较fashion 一点~而且List View很多细节不好控制,尤其是它的Item的Layout自己设计但是用处不大。好麻烦的感觉!

根据以上的基本思路我自己写了个简单的Demo巩固学习!
Demo详细记录单独放,这样就不会显得那么臃肿!Demo下载地址

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值