<第一行代码>chapter7 ContentPro

作者: HeilHelloWorld | 来源:发表于2016-04-03 17:20 被阅读369次

    内容提供器

    思维导图

    最近在练习使用思维导图,献一下丑。。。

    chapter7

    什么是内容提供器

    内容提供器主要用于在不同应用程序间实现数据共享的功能,它提供了一套完整的机制,允许一个程序访问另一个程序里的数据,同时还能保证被访问数据的安全性。内容提供器可以选择要分享的数据,保证应用程序的隐私数据。一般有两种内容提供器的用法:

    1. 一个是使用现有的内容提供器来读取和操作相应程序中的数据。
    2. 创建自己的内容提供器给自己的应用程序数据提供外部访问接口。

    访问其他程序中的数据

    ContentResolver的基本用法

    获取实例
    Context.getContentResolver();
    

    getContentResolver()方法可以获取一个ContentResolver的实例。

    通过ContentResolver实例对数据进行操作

    ContentResolver对数据也有CRUD这些操作。不过不同于SQLiteDatabase,这几个方法并不接受数据库表名,使用一个Uri参数代替了表名,

    内容Uri给内容提供器中的数据建立了一个唯一标识符,由权限和路径两部分构成。

    权限是用于对不同应用程序进行区分的,一般会采用程序包名来进行命名。
    路径则是对同一应用程序的不同表做区分。

    一般还要在头部加上协议声明,下面是一个示例:

    content://com.example/app/provider/table
    

    获取Uri对象的方法:

    Uri uri = Uri.parse("content://com.example/app/provider/table");
    
    1. 查询

       Cursor cursor = getContentResolver.query(Uri,
                           projection,selection,selectionArgs,sortOrder);
      

      同样返回一个Cursor对象。

      参数:uri(指定查询位置),projection(指定查询的列名),selection(指定where的约束条件),selectionArgs(为where中的占位符提供值),sortOrder(指定查询结果的排列顺序)。

    2. 增加

       //插入一条姓名hello年龄10岁的数据
       ContentValue values = new ContentValue();
       values.put("name", "hello");
       values.put("age", 10);
       getContentResolver.insert(uri, values);
      
    3. 删除

       //删除姓名为hello的数据
       getContentReslover.delete(uri, "name = ?", new String[] {"hello"});
      
    4. 更新

       //更新姓名
       ContentValue values = new ContentValue();
       values.put("name", "haha");
       getContentReslover.update(uri, values, "name = ? and age = ?", 
               new String[] {"haha", "10"});
      
    小实践:读取系统联系人
    1. 获取Cursor对象

       Cursor cursor = null;
       try {
           //获取用来遍历的cursor对象
           cursor = getContentResolver.query(
               ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
               null,null,null,null);
       } catch (Exception e) {
           e.printStackTrace();
       } finally {
           if(cursor != null) {
               cursor.close();
           }
       }
      

      ContactsContract.CommonDataKinds.Phone.CONTENT_URI是我们要读取的Uri的封装变量,来自于ContactsContract.CommonDataKinds.Phone类。

    2. 遍历读取每行数据

       while(cursor.moveToNext()) {
           //获取联系人姓名
           String name  = cursor.getString(cursor.getColumnIndex(
               ContactsContract.CommonDataKinds.Phone.Number));
       }
      
    3. 对数据进行操作

       //操作吧。。。随意操作。
      

    创建自己的内容提供器

    1. 创建内容提供器继承自ContentProvider

       public class MyProvider extends ContentProvider {
      
           @Override
           public boolean onCreate() {
               return false;
           }
       
           @Nullable
           @Override
           public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
               return null;
           }
       
           @Nullable
           @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;
           }
       
           @Nullable
           @Override
           public String getType(Uri uri) {
               return null;
           }
       }
      

      这六个方法是必须要实现的

      onCreate():初始化内容提供器的时候调用,通常会在这里完成对数据库的创建和升级操作
      返回值对应了创建和升级操作的成功与否。只有当ContentResolver访问我们的数据时,内容提供器才会被初始化。

      query():uri指定查询表名,projection用于确定是哪些列,selection代表约束,selectionArgs代表约束里占位符的值,sortOrder确定查询返回数据的排列顺序。

      insert():uri指定插入表名,values携带数据,返回一个用于表示这条新纪录的Uri对象

      update():uri指定更新表名,valuse携带要更新的数据,selection代表约束,selectionArgs代表约束里占位符的值。返回更新的行号

      delete():uri指定更新表名,selection代表约束,selectionArgs代表约束里占位符的值。返回被删除的行数。

      getType():根据传入的内容Uri返回相应的MIME类型。

      query()

      这里query需要返回一个cursor,怎么去根据传入的参数去确认要返回的cursor呢,这里就用到了UriMatcher来对传入的uri进行匹配,剩下的内容就很容易了。

       public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
      
           Cursor cursor = null;
      
           switch (uriMatcher.match(uri)) {
               case TABLE1_DIR:
                   SQLiteDatabase database =
                   break;
               case TABLE1_ITEM:
                   break;
               case TABLE2_DIR:
                   break;
               case TABLE2_ITEM:
                   break;
               default:
                   break;
           }
           return cursor;
       }
      

      getType()

      getType是provider里面必须要实现的一个方法,这里返回一个MIME类型的字符串。
      public String getType(Uri uri) {
      switch (uriMatcher.match(uri)) {
      case TABLE1_DIR:
      return "vnd.android.cursor.dir/vnd.com.learn.app.provider.table1";
      break;
      case TABLE1_ITEM:
      return "vnd.android.cursor.item/vnd.com.learn.app.provider.table1";
      break;
      default:
      return null;
      break;
      }
      return null;
      } MIME类型由三个部分组成:

      1. 必须以vnd开头
      2. 如果uri是以路径结尾,则后接.android.cursor.dir/如果以ID结尾,则后接.android.cursor.item/
      3. 最后接上vnd.<authority>.<path>

      例如content://com.hello.app.provider.table这个Uri对应的MIME 字符串就是:
      vnd.android.cursor.dir/vnd.com.hello.app.provider.table

       public String getType(Uri uri) {
           switch (uriMatcher.match(uri)) {
               case TABLE1_DIR:
                   return "vnd.android.cursor.dir/vnd.com.learn.app.provider.table1";
                   break;
               case TABLE1_ITEM:
                   return "vnd.android.cursor.item/vnd.com.learn.app.provider.table1";
                   break;
               default:
                   return null;
                   break;
           }
           return null;
       }
      

    实现跨程序数据共享

    这一节写了很多代码,但是核心的点就是在于自定义的ContentProvider里面那六个方法分别的具体实现。

    1.实现自己的Provider以后其他应用就可以通过这个provider来读取我们的数据。这里算是上面内容的一个结合吧。需要注意的有几个点:

    query()方法里访问单条数据的时候可能需要用到Id,这里Uri对象提供了一个getPathSegmengts()方法,以"/"把uri内容分割放到字符串数组中。这样可以通过取数组[1]的位置得到id
    最后还要在AndroidManifest.xml文件里注册内容提供器

    <provider
        android:name="com.xx.xx.provider"
        android:authorities="com.xx.xxx.xx"
        android.exported="true"
    </provider>
    

    2.去操作上面那个provider提供的数据

    使用getContentResolver()来进行各种操作。

    总结

    ContentProvider的存在使得应用程序之间数据共享与数据共享时的安全得以共存,不必担心数据泄露。

    不知不觉写到了第七章,有过想放弃的时候,但是想想还是善始善终,不忘初心。记录下来学习的点点滴滴。嗯,就是这样。

    相关文章

      网友评论

        本文标题:<第一行代码>chapter7 ContentPro

        本文链接:https://www.haomeiwen.com/subject/cqsulttx.html