题记:这篇是对content provider的一个全局的认识篇,包括一些基本概念和用法,故而借用下大酒神的大菊观附体~

主要包括以下几个方面:

  • provider执行原理以及相关的概念;
  • 通过provider来存储数据;
  • provider的三大类型,以及不同的试用情况;
  • provider的工具类(contect class和mime类型)。

  content provider主要是用来支持跨应用访问数据,如果只是本身应用程序使用数据,那么直接使用SQLiteDataBase就可以了。按我的理解是,content provider封装了一些和android底层数据的操作,向外提供了统一的接口。contentResolver又是什么呢?按我的理解是,建立在很多具体的content provider基础之上的一个工具类,同时封装实现了content provider的那些数据访问接口,统一了再上一层也就是客户端的调用。这样客户端只需要一种调用方式,而不需要管调用的是哪个应用的数据,这些跨进程的访问细节都被contentResolver给屏蔽掉了。那么这时候客户端调用数据需要有一个统一的调用方式,就是通过content URI来实现访问。content URI规定了访问数据的一个标准。同时,若要访问非数据库一类的资源,也可以通过MIME类型的表示来访问,只不过表现形式不一样而已。

 一、provider执行原理已经相关概念

  实际上,访问数据都是先通过contentResolver的相应方法,如查询时,contentResolver.query()方法,实际上,其内部调用的相关content provider的query()方法。一切需要通过content provider的操作,都可以通过contentResolver的相应操作来实现。

  相关概念:

  •  content URI:资源标识符,用来访问指定content Provider的指定资源。形式如下         
 content://schema/resource

 

   其中:content://为固定头部,shema为具体的content provider标识,resource为具体content provider提供的资源标识,如表名words;

  • projection:查询时需要显示的列集合,为一字符串数组;
  • selection:查询条件表达式字符串
  • selectionArgs:用来匹配查询条件表达式中的?标识符,使得查询更加严谨,主要是为了防止SQL注入等恶意输入的情况;
  • sortOrder:排序条件,和sql查询一样的排序

  最终,其组合而成的还是一个SQL查询语句,查询到指定资源并返回。

  二、provider存储数据

  1. 读取数据。
    从content provider读取数据,首先需要相关被请求的content provider的读取权限,并且相关权限需要在AndroidManifest.xml中的user-permission节点中声明。
    组织查询条件,定义好需要查询的列集合,查询条件等。query方法返回的是cursor对象,也称游标。若cursor为null或者query方法直接抛出异常,则表示query方法执行时异常;正常cursor不为空,其cursor.getCount()方法返回值大于等于0的。cursor对象可以自由的访问其包含的行和列对象,同时返回的数据类型不超过其支持的那几种:int ,long,float,double,blob。cursor能够根据查询目标更新而自动更新。
    展示Cursor中的查询结果包括两种方式:
        一是直接将Cursor对象当作参数传递到SimpleCursorAdapter对象中,展示在listView中。这时需要有_id一列。
        二是直接读取Cursor对象中的值:
    if (mCursor != null) {
       (mCursor.moveToNext()) {
    
            // Gets the value from the column.
            newWord = mCursor.getString(index);
        }
    } else {
    
        // Insert code here to report an error if the cursor is null or the provider threw an exception.
    }
  2. 写入数据。
    写入包括以下三种类型的操作:
    a).insert。
        通过ContentValues对象的put方法,将相应字段的对应值放入该对象中。若要放入空值,使用putNull。
    Uri mNewUri;
    
    ...
    
    // Defines an object to contain the new values to insert
    ContentValues mNewValues = new ContentValues();
    
    /*
     * Sets the values of each column and inserts the word. The arguments to the "put"
     * method are "column name" and "value"
     */
    mNewValues.put(UserDictionary.Words.APP_ID, "example.user");
    mNewValues.put(UserDictionary.Words.LOCALE, "en_US");
    mNewValues.put(UserDictionary.Words.WORD, "insert");
    mNewValues.put(UserDictionary.Words.FREQUENCY, "100");
    
    mNewUri = getContentResolver().insert(
        UserDictionary.Word.CONTENT_URI,   // the user dictionary content URI
        mNewValues                          // the values to insert
    );

        同时insert方法返回uri,指向新增加的一行,可以通过ContentUris.parseId(),获取该URI中表示的ID。
    b).update。
        通过ContentValues对象把要更新的字段写入其中,contentResolver.update()方法返回的是已更新的行数。
    c).delete。
        contentResolver.delete()方法返回的是已删除的行数。

三、访问Provider的三大方式

  1. 批量访问(batch access):通过ContentProviderOperation类型来创建批量操作,并且通过contentResolver.applyBatch()方法来实现;
  2. 通过intent来访问,适用于没有设定权限而又想访问其他应用的数据时。直接通过intent来访问,然后根据返回的uri再来获取对应的值;
  3. 异步加载数据,常用的有CursorLoader。

四、工具类

  • 工具类实际是用来标识content provider所要控制的数据一个结构描述,如某张表下有哪些列,基本content uri字符串是什么等一些能够描述content provider里面的数据的。
  • content provider URI返回值也可以包括两种MIME类型:标准的MIME和自定义的MIME。
    标准的MIME如:text/html,前面的是类型,后面的是子类型。
    自定义的MIME类型:
    vnd.android.cursor.dir
    表示类型或者多行,而下面的表示一行或者一条数据:
    vnd.android.cursor.item

     


    还是蛮有意思的,和正常的content uri对比,详见SDK文档。

另外,本文中引用的代码片段来自SDK官方学习文档,转载请说明出处~~

posted on 2013-01-30 21:59  西瓜瓜瓜瓜瓜  阅读(327)  评论(0编辑  收藏  举报