Android 四大组件之Content Provider

来源:互联网 发布:linux检查文件是否存在 编辑:程序博客网 时间:2024/05/17 08:57

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);      }  }
0 0