Android 四大组件之Content Provider

ContentProvider的定义

为存储和获取数据提供统一的接口。可以在不同的应用程序之间共享数据。

ContentProvider提供的方法

  • query:查询
  • insert:插入
  • update:更新
  • delete:删除
  • getType:得到数据类型
  • onCreate:创建数据时调用的回调函数

ContentProvider的特点

1)、ContentProvider为存储和获取数据提供了统一的接口。ContentProvide对数据进行封装,不用关心数据存储的细节。使用表的形式来组织数据。
2)、使用ContentProvider可以在不同的应用程序之间共享数据。
3)、Android为常见的一些数据提供了默认的ContentProvider(包括音频、视频、图片和通讯录等)。

Uri的介绍

用到ContentProvider 就不得不介绍一下Uri了 因为ContentProvider的对外提供的数据就是用URI形式体现的。

Uri代表了要操作的数据,Uri主要包含了两部分信息:
1、需要操作的ContentProvider ,
2、对ContentProvider中的什么数据进行操作,

例如:content://com.zhi.example.myprovider/tablename/id

一个Uri由以下几部分组成:
1. 标准前缀,用来说明一个Content Provider控制这些数据,无法改变的;”content://”
2. URI 的标识,用于唯一标识这个ContentProvider,外部调用者可以根据这个标识来找到它。它定义了是哪个ContentProvider提供这些数据。对于第三方应用程序,为了保证URI标识的唯一性,它必须是一个完整的、小写的类名。这个标识在元素的authorities属性中说明:一般是定义该ContentProvider的包.类的名称。 例如:com.zhi.contentprovider.mycontentprovider
3. 路径(path),通俗的讲就是你要操作的数据库中表的名字,或者你也可以自己定义,记得在使用的时候保持一致就可以了;”content://com.zhi.contentprovider.mycontentprovider/tablename”
4. 如果URI中包含表示需要获取的记录的ID;则就返回该id对应的数据,如果没有ID,就表示返回全部;
“content://com.zhi.contentprovider.mycontentprovider/tablename/#” #表示数据id。


另外:
路径(path)可以用来表示我们要操作的数据,路径的构建应根据业务而定,如下:
要操作person表中id为10的记录,可以构建这样的路径:/person/10
要操作person表中id为10的记录的name字段, person/10/name
要操作person表中的所有记录,可以构建这样的路径:/person
要操作xxx表中的记录,可以构建这样的路径:/xxx
当然要操作的数据不一定来自数据库,也可以是文件、xml或网络等其他存储方式,如下:
要操作xml文件中person节点下的name节点,可以构建这样的路径:/person/name
如果要把一个字符串转换成Uri,可以使用Uri类中的parse()方法,如下:
Uri uri = Uri.parse(“content://com.zhi.contentprovider.mycontentprovider/person”)

UriMatcher类

Uri代表了要操作的数据,所以我们需要解析Uri,并从Uri中获取数据。Android系统提供了两个用于操作Uri的工具类,分别为UriMatcher和ContentUris 。掌握它们的使用,会便于我们的开发工作。

UriMatcher类用于匹配Uri,它的用法如下:

1、 初始化

//常量UriMatcher.NO_MATCH表示不匹配任何路径的返回码
UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);  

2、 注册需要的Uri

matcher.addURI("com.zhi.mycontentprovider", "people", PEOPLE);  
matcher.addURI("com.zhi.mycontentprovider", "person/#", PEOPLE_ID);  

3、 对已经注册的Uri进行匹配:

Uri uri = Uri.parse("content://" + "com.zhi.mycontentprovider" + "/people");  
//匹配,并得到返回码
int match = matcher.match(uri);  
//对返回码进行分析,返回响应的Uri;
switch (match)  
{  
   case PEOPLE:  
       return "vnd.android.cursor.dir/people";  
   case PEOPLE_ID:  
       return "vnd.android.cursor.item/people";  
   default:  
       return null;  
}  

ContentUris类

ContentUris类用于操作Uri路径后面的ID部分,它有两个比较实用的方法

1、public static Uri withAppendedId(Uri contentUri, long id)

这个方法负责把id和contentUri连接成一个新的Uri。
例如 contentUri为content://com.bing.provider.personprovider/person
id为10
那么使用这个方法返回的新的Uri的值为content://com.zhi.mycontentprovider/person/10

2、 public static long parseId(Uri contentUri)

这个方法负责把content URI 后边的id解析出来,比如现在这个content URI 是content://com.zhi.mycontentprovider/person/10,
那么这个函数的返回值就是10。

如何使用ContentProvider

1、自定义一个类,继承SQLiteOpenHelper,并实现数据库的创建
2、自定义一个类,继承ContentProvider ,实现数据的增删查更新等操作。
3、在Activity获取一个ContentResolver实例 ,用ContentResolver来管理ContentProvider,
4、在AndroidManifest.xml中注册自定义的ContentProvider 类

下面通过一个自己test的例子来说明一下:

实现一个类DatabaseHelper继承SQLiteOpenHelper

package com.zhi.contentprovider;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

import com.zhi.contentprovider.Provider.PersonColumns;

/**
 * SQL数据库的创建 
 * @author zhi
 *
 */
public class DatabaseHelper extends SQLiteOpenHelper {
    //数据库的名称
    private final static String DATABASE_NAME="dbZhi.db";
    //数据库的版本号
    private final static int DATABASE_VERSION =1;

    public DatabaseHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
        // TODO Auto-generated constructor stub
    }
    @Override
    public void onCreate(SQLiteDatabase db) {
        // TODO Auto-generated method stub
        //创建一个Person的表
        db.execSQL("CREATE TABLE " + PersonColumns.TABLE_NAME + " ("  
                + PersonColumns._ID + " INTEGER PRIMARY KEY,"  
                + PersonColumns.NAME + " TEXT,"  
                + PersonColumns.AGE + " INTEGER"  
                + ");");  
    }
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        // TODO Auto-generated method stub
        //当有数据库更新时,删掉这个表,并重新创建(注意,在实际编程中,存在表中的数据一般都是重要的,不能这删除表,应该在现有表的基础上增加字段等操作)
         db.execSQL("DROP TABLE IF EXISTS " + PersonColumns.TABLE_NAME);  
         onCreate(db);
    }
}

实现一个类PersionProvide继承ContentProvider

package com.zhi.contentprovider;

import java.util.HashMap;

import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.text.TextUtils;

/**
 * 内容提供者组件
 * @author zhi
 *
 */
public class PersionProvide extends ContentProvider {
    //声明一个集合变量
    private static HashMap<String, String> sPersonsProjectionMap;  
    //创建代号
    private static final int PERSONS = 1;  
    private static final int PERSONS_ID = 2;  

    private static final UriMatcher sUriMatcher;  

    private DatabaseHelper mOpenHelper;  


    @Override
    public boolean onCreate() {
        // TODO Auto-generated method stub
        //初始化一个DatabaseHelper实例
        mOpenHelper=new DatabaseHelper(getContext());
        return true;
    }


    @Override
    public Cursor query(Uri uri, String[] projection, String selection,
            String[] selectionArgs, String sortOrder) {
        // TODO Auto-generated method stub
        //查询操作
        return null;
    }

    @Override
    public String getType(Uri uri) {
        // TODO Auto-generated method stub
        //返回数据类型
         switch (sUriMatcher.match(uri)) {  
            case PERSONS:  
                return Provider.CONTENT_TYPE;  
            case PERSONS_ID:  
                return Provider.CONTENT_ITEM_TYPE;  
            default:  
                throw new IllegalArgumentException("Unknown URI " + uri);  
            }  
    }

    @Override
    public Uri insert(Uri uri, ContentValues values) {
        // TODO Auto-generated method stub
        //插入数据
         if (sUriMatcher.match(uri) != PERSONS) {  
                throw new IllegalArgumentException("Unknown URI " + uri);  
            }  

         ContentValues values2 = null;
         if (null!=values) {
             values2=new ContentValues(values);
         }else {
            values=new ContentValues();
        }

        // Make sure that the fields are all set  
        if (values2.containsKey(Provider.PersonColumns.NAME) == false) {  
            values2.put(Provider.PersonColumns.NAME, "");  
        }  

        if (values2.containsKey(Provider.PersonColumns.AGE) == false) {  
            values2.put(Provider.PersonColumns.AGE, 0);  
        }  


        SQLiteDatabase db = mOpenHelper.getWritableDatabase();  
        long rowId = db.insert(Provider.PersonColumns.TABLE_NAME, Provider.PersonColumns.NAME, values2);
        if (rowId > 0) {  
            Uri noteUri = ContentUris.withAppendedId(Provider.PersonColumns.CONTENT_URI, rowId);  
            getContext().getContentResolver().notifyChange(noteUri, null);  
            return noteUri;  
        }  
        throw new SQLException("Failed to insert row into " + uri);  

    }

    @Override
    public int delete(Uri uri, String where, String[] whereArgs) {
        // TODO Auto-generated method stub
        //删除数据
         SQLiteDatabase db = mOpenHelper.getWritableDatabase();  
            int count;  
            switch (sUriMatcher.match(uri)) {  
            case PERSONS:  
                count = db.delete(Provider.PersonColumns.TABLE_NAME, where, whereArgs);  
                break;  
            case PERSONS_ID:  
                String noteId = uri.getPathSegments().get(1);  
                count = db.delete(Provider.PersonColumns.TABLE_NAME, Provider.PersonColumns._ID + "=" + noteId  
                        + (!TextUtils.isEmpty(where) ? " AND (" + where + ')' : ""), whereArgs);  
                break;  

            default:  
                throw new IllegalArgumentException("Unknown URI " + uri);  
            }  

            getContext().getContentResolver().notifyChange(uri, null);  
            return count;  
    }

    @Override
    public int update(Uri uri, ContentValues values, String where,
            String[] whereArgs) {
        // TODO Auto-generated method stub
        //更新数据
         SQLiteDatabase db = mOpenHelper.getWritableDatabase();  
            int count;  
            switch (sUriMatcher.match(uri)) {  
            case PERSONS:  
                count = db.update(Provider.PersonColumns.TABLE_NAME, values, where, whereArgs);  
                break;  

            case PERSONS_ID:  
                String noteId = uri.getPathSegments().get(1);  
                count = db.update(Provider.PersonColumns.TABLE_NAME, values, Provider.PersonColumns._ID + "=" + noteId  
                        + (!TextUtils.isEmpty(where) ? " AND (" + where + ')' : ""), whereArgs);  
                break;  

            default:  
                throw new IllegalArgumentException("Unknown URI " + uri);  
            }  

            getContext().getContentResolver().notifyChange(uri, null);  
            return count;  
    }

    static {  
        sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);  
        // 这个地方的persons要和PersonColumns.CONTENT_URI中最后面的一个Segment一致  
        sUriMatcher.addURI(Provider.AUTHORITY, "persons", PERSONS);  
        sUriMatcher.addURI(Provider.AUTHORITY, "persons/#", PERSONS_ID);  

        sPersonsProjectionMap = new HashMap<String, String>();  
        sPersonsProjectionMap.put(Provider.PersonColumns._ID, Provider.PersonColumns._ID);  
        sPersonsProjectionMap.put(Provider.PersonColumns.NAME, Provider.PersonColumns.NAME);  
        sPersonsProjectionMap.put(Provider.PersonColumns.AGE, Provider.PersonColumns.AGE);  
    }  

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值