zoukankan      html  css  js  c++  java
  • Android Content Provider介绍

    一、ContentProvider的概念
      ContentProvider:为存储和获取数据提供统一的接口。可以在不同的应用程序之间共享数据。Android已经为常见的一些数据提供了默认的ContentProvider
      1、ContentProvider使用表的形式来组织数据
       无论数据的来源是什么,ContentProvider都会认为是一种表,然后把数据组织成表格
      2、ContentProvider提供的方法
       query:查询
       insert:插入
       update:更新
       delete:删除
       getType:得到数据类型
       onCreate:创建数据时调用的回调函数
      3、每个ContentProvider都有一个公共的URI,这个URI用于表示这个ContentProvider所提供的数据。Android所提供的ContentProvider都存放在android.provider包当中
      二、ContentProvider的内部原理
      自定义一个ContentProvider,来实现内部原理
      步骤:
      1、定义一个CONTENT_URI常量(里面的字符串必须是唯一)
      Public static final Uri CONTENT_URI = Uri.parse("content://com.WangWeiDa.MyContentprovider");
      如果有子表,URI为:
      Public static final Uri CONTENT_URI = Uri.parse("content://com.WangWeiDa.MyContentProvider/users");
      2、定义一个类,继承ContentProvider
      Public class MyContentProvider extends ContentProvider
      3、实现ContentProvider的所有方法(query、insert、update、delete、getType、onCreate)
      package com.WangWeiDa.cp;
      
      import java.util.HashMap;
      
      import com.WangWeiDa.cp.MyContentProviderMetaData.UserTableMetaData;
      import com.WangWeiDa.data.DatabaseHelp;
      
      import android.content.ContentProvider;
      import android.content.ContentUris;
      import android.content.ContentValues;
      import android.content.UriMatcher;
      import android.database.Cursor;
      import android.database.sqlite.SQLiteDatabase;
      import android.database.sqlite.SQLiteQueryBuilder;
      import android.net.Uri;
      import android.text.TextUtils;
      
      public class MyContentProvider extends ContentProvider {
       //访问表的所有列
       public static final int INCOMING_USER_COLLECTION = 1;
       //访问单独的列
       public static final int INCOMING_USER_SINGLE = 2;
       //操作URI的类
       public static final UriMatcher uriMatcher;
       //为UriMatcher添加自定义的URI
       static{
       uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
       uriMatcher.addURI(MyContentProviderMetaData.AUTHORITIES,"/user",
       INCOMING_USER_COLLECTION);
       uriMatcher.addURI(MyContentProviderMetaData.AUTHORITIES,"/user/#",
       INCOMING_USER_SINGLE);
      
       }
       private DatabaseHelp dh;
       //为数据库表字段起别名
       public static HashMap userProjectionMap;
       static
       {
       userProjectionMap = new HashMap();
       userProjectionMap.put(UserTableMetaData._ID,UserTableMetaData._ID);
       userProjectionMap.put(UserTableMetaData.USER_NAME, UserTableMetaData.USER_NAME);
       }
       /**
       * 删除表数据
       */
       @Override
       public int delete(Uri uri, String selection, String[] selectionArgs) {
       System.out.println("delete");
       //得到一个可写的数据库
       SQLiteDatabase db = dh.getWritableDatabase();
       //执行删除,得到删除的行数
       int count = db.delete(UserTableMetaData.TABLE_NAME, selection, selectionArgs);
       return count;
       }
       /**
       * 数据库访问类型
       */
       @Override
       public String getType(Uri uri) {
       System.out.println("getType");
       //根据用户请求,得到数据类型
       switch (uriMatcher.match(uri)) {
       case INCOMING_USER_COLLECTION:
       return MyContentProviderMetaData.UserTableMetaData.CONTENT_TYPE;
       case INCOMING_USER_SINGLE:
       return MyContentProviderMetaData.UserTableMetaData.CONTENT_TYPE_ITEM;
       default:
       throw new IllegalArgumentException("UnKnown URI"+uri);
       }
       }
       /**
       * 插入数据
       */
       @Override
       public Uri insert(Uri uri, ContentValues values) {
       //得到一个可写的数据库
       SQLiteDatabase db = dh.getWritableDatabase();
       //向指定的表插入数据,得到返回的Id
       long rowId = db.insert(UserTableMetaData.TABLE_NAME, null, values);
       if(rowId > 0){//判断插入是否执行成功
       //如果添加成功,利用新添加的Id和
       Uri insertedUserUri = ContentUris.withAppendedId(UserTableMetaData.CONTENT_URI, rowId);
       //通知监听器,数据已经改变
       getContext().getContentResolver().notifyChange(insertedUserUri, null);
       return insertedUserUri;
       }
       return uri;
       }
       /**
       * 创建ContentProvider时调用的回调函数
       */
       @Override
       public boolean onCreate() {
       System.out.println("onCreate");
       //得到数据库帮助类
       dh = new DatabaseHelp(getContext(),MyContentProviderMetaData.DATABASE_NAME);
       return false;
       }
       /**
       * 查询数据库
       */
       @Override
       public Cursor query(Uri uri, String[] projection, String selection,
       String[] selectionArgs, String sortOrder) {
       //创建一个执行查询的Sqlite
       SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
       //判断用户请求,查询所有还是单个
       switch(uriMatcher.match(uri)){
       case INCOMING_USER_COLLECTION:
       //设置要查询的表名
       qb.setTables(UserTableMetaData.TABLE_NAME);
       //设置表字段的别名
       qb.setProjectionMap(userProjectionMap);
       break;
       case INCOMING_USER_SINGLE:
       qb.setTables(UserTableMetaData.TABLE_NAME);
       qb.setProjectionMap(userProjectionMap);
       //追加条件,getPathSegments()得到用户请求的Uri地址截取的数组,get(1)得到去掉地址中/以后的第二个元素
       qb.appendWhere(UserTableMetaData._ID + "=" + uri.getPathSegments().get(1));
       break;
       }
       //设置排序
       String orderBy;
       if(TextUtils.isEmpty(sortOrder)){
       orderBy = UserTableMetaData.DEFAULT_SORT_ORDER;
       }
       else{
       orderBy = sortOrder;
       }
       //得到一个可读的数据库
       SQLiteDatabase db = dh.getReadableDatabase();
       //执行查询,把输入传入
       Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, orderBy);
       //设置监听
       c.setNotificationUri(getContext().getContentResolver(), uri);
       return c;
      
       }
       /**
       * 更新数据库
       */
       @Override
       public int update(Uri uri, ContentValues values, String selection,
       String[] selectionArgs) {
       System.out.println("update");
       //得到一个可写的数据库
       SQLiteDatabase db = dh.getWritableDatabase();
       //执行更新语句,得到更新的条数
       int count = db.update(UserTableMetaData.TABLE_NAME, values, selection, selectionArgs);
       return count;
       }
      
      }
      
      4、在AndroidMinifest.xml中进行声明
        


       android:name=".cp.MyContentProvider"
      


       android:authorities="com.WangWeiDa.cp.MyContentProvider"
       />
      **为ContentProvider提供一个常量类MyContentProviderMetaData.java
      package com.WangWeiDa.cp;
      
      import android.net.Uri;
      import android.provider.BaseColumns;
      
      public class MyContentProviderMetaData {
       //URI的指定,此处的字符串必须和声明的authorities一致
       public static final String AUTHORITIES = "com.wangweida.cp.MyContentProvider";
       //数据库名称
       public static final String DATABASE_NAME = "myContentProvider.db";
       //数据库的版本
       public static final int DATABASE_VERSION = 1;
       //表名 
       public static final String USERS_TABLE_NAME = "user";
       
       public static final class UserTableMetaData implements BaseColumns{
       //表名
       public static final String TABLE_NAME = "user";
       //访问该ContentProvider的URI
       public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITIES + "/user");
       //该ContentProvider所返回的数据类型的定义
       public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.myprovider.user";
       public static final String CONTENT_TYPE_ITEM = "vnd.android.cursor.item/vnd.myprovider.user";
       //列名
       public static final String USER_NAME = "name";
       //默认的排序方法
       public static final String DEFAULT_SORT_ORDER = "_id desc";
       }
      
      }

     
  • 相关阅读:
    Nullable<T>、Nullable、null、?修饰符的区别
    使用EF CodeFirst连接MySql数据库
    C# 在项目中配置Log4net
    我的Visual Studio必用工具
    面向对象原则之一 接口隔离原则
    面向对象原则之一 依赖倒置原则
    C# ABP
    面向对象原则之一 开放封闭原则(开闭原则)
    面向对象原则之一 单一职责原则
    C# Owin初探 概念理解(一)
  • 原文地址:https://www.cnblogs.com/Dionexin/p/5821728.html
Copyright © 2011-2022 走看看