Android四大组件之ContentProvider实现

   最近在看ContentProvider的知识,现在写一篇博客总结一下。实现ContentProvider必须扩展android.content.ContentProvider并实现以下重要方法:query、insert、update、delete和getType。在实现它们之前也需要进行大量设置。主要有以下几个步骤:

(1)、计划数据库、URI及列名等,创建元数据类来定义所有这些元数据元素的常量。

(2)、扩展抽象类ContentProvider。

(3)、实现方法:query、insert、update、delete和getType。

(4)、在配置文件中注册ContentProvider。

  1、计划数据库

   我将创建一个包含一系列图书的数据库。这个图书数据库仅包含一个books表,该表的列包括name、isbn和author。这些列名对应着元数据,这些相关的元数据将在Java类中定义。定义元数据的Java类为BookProviderMetaData,代码如下:

/**
 * book class
 * 
 * @author Pan
 * 
 */
public class BookProviderMetaData {
	public static final String AUTHORITY = "com.androidbook.provider.BookProvider";

	public static final String DATABASE_NAME = "book.db";
	public static final int DATABASE_VERSION = 1;
	public static final String BOOKS_TABLE_NAME = "books";

	private BookProviderMetaData() {
	}

	/**
	 * inner class describing BookTable
	 * 
	 * @author Pan
	 * 
	 */
	public static final class BookTableMetaData implements BaseColumns {

		private BookTableMetaData() {
		}

		public static final String TABLE_NAME = "books";

		// uri and MIME type definitions
		public static final Uri CONTENT_URI = Uri.parse("content://"
				+ AUTHORITY + "/books");

		public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.androidbook.book";

		public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.androidbook.book";

		public static final String DEFAULT_SORT_ORDER = "modified DESC";

		// additional column start here
		// string type
		public static final String BOOK_NAME = "name";
		public static final String BOOK_ISBN = "isbn";
		public static final String BOOK_AUTHOR = "author";
		// Integer from System.currentTimeMillis()
		public static final String CREATED_DATE = "created";
		public static final String MODIFIED_DATE = "modified";
	}

}
  2、扩展ContentProvider

   实现BookProvider示例ContentProvider涉及扩展ContentProvider类,重写onCreate()来创建数据库,然后实现query、insert、update、delete和getType方法。代码如下:

/**
 * BookProvider class
 * 
 * @author Pan
 * 
 */
public class BookProvider extends ContentProvider {
	// logging helper tag. no significance to provider
	private static final String TAG = "BookProvider";

	// setup projection map
	// Projection maps are similar to "as" (column alias) construct
	// in an sql statement where by you can rename the columns.
	private static HashMap<String, String> sBooksProjectionMap;

	static {
		sBooksProjectionMap = new HashMap<String, String>();
		sBooksProjectionMap.put(BookTableMetaData._ID, BookTableMetaData._ID);
		// name isbn author
		sBooksProjectionMap.put(BookTableMetaData.BOOK_NAME,
				BookTableMetaData.BOOK_NAME);
		sBooksProjectionMap.put(BookTableMetaData.BOOK_ISBN,
				BookTableMetaData.BOOK_ISBN);
		sBooksProjectionMap.put(BookTableMetaData.BOOK_AUTHOR,
				BookTableMetaData.BOOK_AUTHOR);
		// created date, modified date
		sBooksProjectionMap.put(BookTableMetaData.CREATED_DATE,
				BookTableMetaData.CREATED_DATE);
		sBooksProjectionMap.put(BookTableMetaData.MODIFIED_DATE,
				BookTableMetaData.MODIFIED_DATE);
	}

	// setup uris: provider a mechanism to identify all the incoming uri
	// patterns.
	private static final UriMatcher sUriMatcher;
	private static final int INCOMING_BOOK_COLLECTION_URI_INDICATOR = 1;
	private static final int INCOMING_SINGLE_BOOK_URI_INDICATOR = 2;
	static {
		sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
		sUriMatcher.addURI(BookProviderMetaData.AUTHORITY, "books",
				INCOMING_BOOK_COLLECTION_URI_INDICATOR);
		sUriMatcher.addURI(BookProviderMetaData.AUTHORITY, "books/#",
				INCOMING_SINGLE_BOOK_URI_INDICATOR);
	}

	/**
	 * setup/create database this class helps open,create,and upgrade the
	 * database file.
	 * 
	 * @author Pan
	 * 
	 */
	private static class DataBaseHelper extends SQLiteOpenHelper {

		public DataBaseHelper(Context context) {
			super(context, BookProviderMetaData.DATABASE_NAME, null,
					BookProviderMetaData.DATABASE_VERSION);
		}

		@Override
		public void onCreate(SQLiteDatabase db) {
			Log.d(TAG, "inner oncreate called");
			db.execSQL("CREATE TABLE " + BookTableMetaData.TABLE_NAME + " ("
					+ BookTableMetaData._ID + " INTEGER PRIMARY KEY,"
					+ BookTableMetaData.BOOK_NAME + " TEXT,"
					+ BookTableMetaData.BOOK_ISBN + " TEXT,"
					+ BookTableMetaData.BOOK_AUTHOR + " TEXT,"
					+ BookTableMetaData.CREATED_DATE + " INTEGER,"
					+ BookTableMetaData.MODIFIED_DATE + " INTEGER,");
		}

		public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
			Log.d(TAG, "inner onUpgrade called");
			Log.w(TAG, "upgrading database from version:" + oldVersion + " to "
					+ newVersion + ", which will destory all old data");
			db.execSQL("DROP TABLE IF EXISTS " + BookTableMetaData.TABLE_NAME);
			onCreate(db);
		}

	}

	private DataBaseHelper mOpenHelper;

	@Override
	public boolean onCreate() {
		Log.d(TAG, "main onCreate called");
		mOpenHelper = new DataBaseHelper(getContext());
		return true;
	}

	@Override
	public Cursor query(Uri uri, String[] projection, String selection,
			String[] selectionArgs, String sortOrder) {
		SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
		switch (sUriMatcher.match(uri)) {
		case INCOMING_BOOK_COLLECTION_URI_INDICATOR:
			qb.setTables(BookTableMetaData.TABLE_NAME);
			qb.setProjectionMap(sBooksProjectionMap);
			break;

		case INCOMING_SINGLE_BOOK_URI_INDICATOR:
			qb.setTables(BookTableMetaData.TABLE_NAME);
			qb.setProjectionMap(sBooksProjectionMap);
			qb.appendWhere(BookTableMetaData._ID + "="
					+ uri.getPathSegments().get(1));
			break;
		default:
			throw new IllegalArgumentException("Unknown URI " + uri);
		}

		// if not sort order is specified use the default
		String orderBy;
		if (TextUtils.isEmpty(sortOrder)) {
			orderBy = BookTableMetaData.DEFAULT_SORT_ORDER;
		} else {
			orderBy = sortOrder;
		}

		// get the database and run the query
		SQLiteDatabase db = mOpenHelper.getReadableDatabase();
		Cursor c = db.query(BookTableMetaData.TABLE_NAME, projection,
				selection, selectionArgs, null, null, orderBy);

		// example of getting a count
		@SuppressWarnings("unused")
		int i = c.getCount();

		// tell the cursor what uri to watch, so it knows when its source data
		// changes
		c.setNotificationUri(getContext().getContentResolver(), uri);
		return c;
	}

	@Override
	public String getType(Uri uri) {
		switch (sUriMatcher.match(uri)) {
		case INCOMING_BOOK_COLLECTION_URI_INDICATOR:
			return BookTableMetaData.CONTENT_TYPE;

		case INCOMING_SINGLE_BOOK_URI_INDICATOR:
			return BookTableMetaData.CONTENT_ITEM_TYPE;
		default:
			throw new IllegalArgumentException("Unknown URI " + uri);
		}
	}

	@Override
	public Uri insert(Uri uri, ContentValues initialValues) {
		if (sUriMatcher.match(uri) != INCOMING_BOOK_COLLECTION_URI_INDICATOR) {
			throw new IllegalArgumentException("Unknown URI " + uri);
		}

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

		Long now = Long.valueOf(System.currentTimeMillis());
		// make sure that the fields are all set
		if (values.containsKey(BookTableMetaData.CREATED_DATE) == false) {
			values.put(BookTableMetaData.CREATED_DATE, now);
		}
		if (values.containsKey(BookTableMetaData.MODIFIED_DATE) == false) {
			values.put(BookTableMetaData.MODIFIED_DATE, now);
		}

		if (values.containsKey(BookTableMetaData.BOOK_NAME) == false) {
			throw new SQLException(
					"Failed to insert row because book name is needed " + uri);
		}

		if (values.containsKey(BookTableMetaData.BOOK_ISBN) == false) {
			values.put(BookTableMetaData.BOOK_ISBN, "Unknown ISBN");
		}
		if (values.containsKey(BookTableMetaData.BOOK_AUTHOR) == false) {
			values.put(BookTableMetaData.BOOK_AUTHOR, "Unknown Author");
		}

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

	@Override
	public int delete(Uri uri, String selection, String[] selectionArgs) {
		SQLiteDatabase db = mOpenHelper.getWritableDatabase();
		int count;
		switch (sUriMatcher.match(uri)) {
		case INCOMING_BOOK_COLLECTION_URI_INDICATOR:
			count = db.delete(BookTableMetaData.TABLE_NAME, selection,
					selectionArgs);
			getContext().getContentResolver().notifyChange(uri, null);
			return count;

		case INCOMING_SINGLE_BOOK_URI_INDICATOR:
			String rowId = uri.getPathSegments().get(1);
			count = db.delete(
					BookTableMetaData.TABLE_NAME,
					BookTableMetaData._ID
							+ "="
							+ rowId
							+ (!TextUtils.isEmpty(selection) ? " AND ("
									+ selection + ')' : ""), selectionArgs);
			getContext().getContentResolver().notifyChange(uri, null);
			return count;
		default:
			throw new IllegalArgumentException("Unknown URI " + uri);
		}

	}

	@Override
	public int update(Uri uri, ContentValues values, String selection,
			String[] selectionArgs) {
		SQLiteDatabase db = mOpenHelper.getWritableDatabase();
		int count;
		switch (sUriMatcher.match(uri)) {
		case INCOMING_BOOK_COLLECTION_URI_INDICATOR:
			count = db.update(BookTableMetaData.TABLE_NAME, values, selection,
					selectionArgs);
			getContext().getContentResolver().notifyChange(uri, null);
			return count;

		case INCOMING_SINGLE_BOOK_URI_INDICATOR:
			String rowId = uri.getPathSegments().get(1);
			count = db.update(
					BookTableMetaData.TABLE_NAME,
					values,
					BookTableMetaData._ID
							+ "="
							+ rowId
							+ (!TextUtils.isEmpty(selection) ? " AND ("
									+ selection + ')' : ""), selectionArgs);
			getContext().getContentResolver().notifyChange(uri, null);
			return count;
		default:
			throw new IllegalArgumentException("Unknown URI " + uri);
		}
	}

}
  3、注册ContentProvider

   在配置文件中注册BookProvider。代码如下:

<provider
            android:name="com.pan.contentproviderdemo.provider.BookProvider"
            android:authorities="com.androidbook.provider.BookProvider" />
  以上就是ContentProvider的实现。本人没有写测试代码。

附上测试代码:http://pan.baidu.com/s/1i37n3Ch



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值