首页 > 代码库 > ContentProvider学习例程

ContentProvider学习例程

ContentProvider总是需要与ContentResolver结合使用,它们之间的关系是:


Context提供了getContentResolver()方法,这个表示Activity、Service等组件都可通过getContentResolver()方法获取ContentResolver对象。

获取了ContentResolver对象之后,接下来就可以调用ContentResolver的query()、insert()、update()和delete()方法

——实际上指定Uri对应的ContentProvider的query()、insert()、update()和delete()


从mars视频学习的例程,主要是在数据库中增加和查询数据


CPActivity.java

public class CPActivity extends Activity {

	public Button queryButton = null;
	public Button insertButton = null;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		queryButton = (Button)findViewById(R.id.query);
		insertButton = (Button)findViewById(R.id.insert);
		queryButton.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				Cursor c = getContentResolver().query(
						FirstProviderMetaData.UserTableMetaData.CONTENT_URI, null,
						null, null, null);
				while(c.moveToNext()){
					System.out.println(c.getString(c.getColumnIndex(UserTableMetaData.USER_NAME)));
				}
				
			}
		});
		insertButton.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				ContentValues values = new ContentValues();
				values.put(FirstProviderMetaData.UserTableMetaData.USER_NAME, "zhangsan");
				Uri uri = getContentResolver().insert(FirstProviderMetaData.UserTableMetaData.CONTENT_URI, values);
				System.out.println("uri-->"+uri.toString());
			}
		});
		System.out.println(getContentResolver().getType(FirstProviderMetaData.UserTableMetaData.CONTENT_URI));
	}
}

FirstContentProvider.java 重写ContentProvider类的query()、insert()方法

public class FirstContentProvider extends ContentProvider {
	
	public static final UriMatcher uriMatcher;//对URI的参数进行判断,是否符合标准,确定该ContentProvider实际能处理的URI
	public static final int INCOMING_USER_COLLECTION = 1;
	public static final int INCOMING_USER_SINGLE = 2;

	private DatabaseHelper dh;
	
	static {
		uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
		uriMatcher.addURI(FirstProviderMetaData.AUTHORITY,"/users",INCOMING_USER_COLLECTION);
		uriMatcher.addURI(FirstProviderMetaData.AUTHORITY, "/users/#", INCOMING_USER_SINGLE);
		
	}
	
	
	public static HashMap<String,String> userProjectionMap;
	static{
		userProjectionMap = new HashMap<String,String>();
		userProjectionMap.put(UserTableMetaData._ID, UserTableMetaData._ID);
		userProjectionMap.put(UserTableMetaData.USER_NAME, UserTableMetaData.USER_NAME);
	}
	
	//是一个回调函数,在contentProvider创建的时候执行
	@Override
	public boolean onCreate() {
		//打开数据库
		dh = new DatabaseHelper(getContext(), FirstProviderMetaData.DATABASE_NAME);
		System.out.println("onCreate");
		return true;
	}
	
	@Override
	public int delete(Uri uri, String selection, String[] selectionArgs) {
		// TODO Auto-generated method stub
		return 0;
	}

	//根据传入的URI,返回该URI所表示的数据类型
	@Override
	public String getType(Uri uri) {
		System.out.println("getType");
		switch(uriMatcher.match(uri)){
		case INCOMING_USER_COLLECTION:
			return UserTableMetaData.CONTENT_TYPE;
		case INCOMING_USER_SINGLE:
			return UserTableMetaData.CONTENT_TYPE_ITEM;
		default:
			throw new IllegalArgumentException("Unknown URI" + uri);
		}
	}

	/**
	 * 该函数的返回值是一个uri,这个uri表示的是刚刚使用这个函数所插入的数据
	 */
	@Override
	public Uri insert(Uri uri, ContentValues values) {
		System.out.println("insert");
		SQLiteDatabase db = dh.getWritableDatabase();
		long rowId = db.insert(UserTableMetaData.TABLE_NAME, null, values);
		if(rowId > 0){
			Uri insertedUserUri = ContentUris.withAppendedId(UserTableMetaData.CONTENT_URI, rowId);
			//通知监听器,数据已经改变
			getContext().getContentResolver().notifyChange(insertedUserUri, null);
			return insertedUserUri;
		}
		throw new SQLException("Failed to insert row into" + uri);
	}



	@Override
	public Cursor query(Uri uri, String[] projection, String selection,
			String[] selectionArgs, String sortOrder) {
		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);
			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.getWritableDatabase();
		Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, orderBy);
		c.setNotificationUri(getContext().getContentResolver(), uri);
		System.out.println("query");
			return c;
	}

	@Override
	public int update(Uri uri, ContentValues values, String selection,
			String[] selectionArgs) {
		// TODO Auto-generated method stub
		return 0;
	}


}


FirstProviderMetaData.java  定义该ContentProvider的常量

public class FirstProviderMetaData {
	public static final String AUTHORITY = "com.mars.testcp.FirstContentProvider";
	public static final String DATABASE_NAME = "FirstProvider.db";
	public static final int DATABASE_VERSION = 1;
	public static final String USERS_TABLE_NAME = "users";
	
	//定义一个静态内部类 定义该ContentProvider所包含的数据列的列名
	public static final class UserTableMetaData implements BaseColumns{
		//表名
		public static final String TABLE_NAME = "users";
		//访问该ContentProvider的URI
		public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/users");
		//该ContentProvider所返回的数据类型的定义,参考帮助文档
		//整张表的数据
		public static final String CONTENT_TYPE = "vnd.android.cursor.dir/nvd.firstprovider.user";
		//表中的一条数据
		public static final String CONTENT_TYPE_ITEM = "vnd.android.cursor.item/nvd.firstprovider.user";
		//列名
		public static final String USER_NAME = "name";
		//默认的排序方法
		public static final String DEFAULT_SORT_ORDER = "_id desc";
		
	}

}

DatabaseHelper.java  创建数据库文件

public class DatabaseHelper extends SQLiteOpenHelper {
	
	private static final int VERSION  = 1;

	//在SQLiteOepnHelper的子类当中,必须有该构造函数
	public DatabaseHelper(Context context, String name, CursorFactory factory,
			int version) {
		//必须通过super调用父类当中的构造函数
		super(context, name, factory, version);
		// TODO Auto-generated constructor stub
	}
	

	public DatabaseHelper(Context context, String name) {
		this(context, name, VERSION);
		// TODO Auto-generated constructor stub
		}
	
	public DatabaseHelper(Context context,String name,int version){
		this(context,name,null,version);
	}

	@Override
	public void onCreate(SQLiteDatabase db) {
		// TODO Auto-generated method stub
		System.out.println("create a Database");
		//execSQL函数用于执行SQL语句,创建一个表名为user,有两列数据id、name
		db.execSQL("create table "+ FirstProviderMetaData.USERS_TABLE_NAME
				+ "(" + FirstProviderMetaData.UserTableMetaData._ID
				+ " INTEGER PRIMARY KEY AUTOINCREMENT,"
				+ FirstProviderMetaData.UserTableMetaData.USER_NAME
				+ " varchar(20));");
		 
	}

	@Override
	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
		// TODO Auto-generated method stub
		System.out.println("update a Database");
		
	}

}


在AndroidManifest.xml文件注册该ContentProvider:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.mars.testcp"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="18" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.mars.testcp.CPActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
       <provider 
           android:name = "com.mars.testcp.FirstContentProvider"
           android:authorities="com.mars.testcp.FirstContentProvider" /> 
    </application>

</manifest>


结果示意图:




ContentProvider学习例程