Android中ContentProvider的意义及用法

ContentProvider提供了标准的接口,供APP跟其他APP共享数据。ContentProvider提供了一种基于使用content://模式的简单URI寻址模型来发布和使用数据的接口。它允许将应用层跟底层数据层分离,通过抽象底层数据源使应用程序不必依赖于某个数据源。

1、示例展示用法

1) MyContentProvider.java

/**
 * 抽象类,实现了ComponentCallbacks2接口
 * <p>在清单文件注册,进程启动时自动创建。</p>
 */
public class MyContentProvider extends ContentProvider {
	private static final String TAG = MyContentProvider.class.getSimpleName();
	public static final Uri CONTENT_URI = Uri.parse("content://com.qinuli.provider.mycontentprovider/elements");
	private static final int ALL_ROWS = 1;
	private static final int SINGLE_ROW = 2;
	private static final UriMatcher URI_MATCHER;
	static{
		URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
		URI_MATCHER.addURI("com.qinuli.provider.mycontentprovider", "elements", ALL_ROWS);
		URI_MATCHER.addURI("com.qinuli.provider.mycontentprovider", "elements/#", SINGLE_ROW);
	}
	private MyDB myDB;
	@Override
	public boolean onCreate() {
		Log.d(TAG, "onCreate");
		myDB = new MyDB(getContext(), MyDB.DATABASE_NAME, null, MyDB.DATABASE_VERSION);
		return true;
	}

	@Override
	public Cursor query(Uri uri, String[] projection, String selection,
			String[] selectionArgs, String sortOrder) {
		SQLiteDatabase db = myDB.getWritableDatabase();
		SQLiteQueryBuilder sqLiteQueryBuilder = new SQLiteQueryBuilder();
		sqLiteQueryBuilder.setTables(MyDB.DATABASE_TABLE);
		switch(URI_MATCHER.match(uri)){
		case SINGLE_ROW:
			String rowID = uri.getPathSegments().get(1);
			sqLiteQueryBuilder.appendWhere(MyDB.KEY_ID+"="+rowID);
			break;
		default:break;
		}
		Cursor cursor = sqLiteQueryBuilder.query(db, projection, selection, selectionArgs, null, null, sortOrder);
		return cursor;
	}

	@Override
	public String getType(Uri uri) {
		switch(URI_MATCHER.match(uri)){
		case ALL_ROWS:
			return "vnd.android.cursor.dir/vnd.qinuli.elemental";
		case SINGLE_ROW:
			return "vnd.android.cursor.item/vnd.qinuli.elemental";
		default:
			throw new IllegalArgumentException("Unsupported URI:"+uri);
		}
	}

	@Override
	public Uri insert(Uri uri, ContentValues values) {
		SQLiteDatabase db = myDB.getWritableDatabase();
		long id = db.insert(MyDB.DATABASE_TABLE, null, values);
		if(id>-1){
			Uri insertedId = ContentUris.withAppendedId(CONTENT_URI, id);
			getContext().getContentResolver().notifyChange(insertedId, null);
			return insertedId;
		}
		return null;
	}

	@Override
	public int delete(Uri uri, String selection, String[] selectionArgs) {
		SQLiteDatabase db = myDB.getWritableDatabase();
		switch(URI_MATCHER.match(uri)){
		case SINGLE_ROW:
			String rowId = uri.getPathSegments().get(1);
			selection = MyDB.KEY_ID+"="+rowId+(TextUtils.isEmpty(selection)?"":" AND ("+selection+')');
			break;
		default:break;
		}
		if(selection==null){
			selection = "1";
		}
		int deleteCount = db.delete(MyDB.DATABASE_TABLE, selection, selectionArgs);
		getContext().getContentResolver().notifyChange(uri, null);
		return deleteCount;
	}

	@Override
	public int update(Uri uri, ContentValues values, String selection,
			String[] selectionArgs) {
		SQLiteDatabase db = myDB.getWritableDatabase();
		switch(URI_MATCHER.match(uri)){
		case SINGLE_ROW:
			String rowId = uri.getPathSegments().get(1);
			selection = MyDB.KEY_ID+"="+rowId+(TextUtils.isEmpty(selection)?"":" AND ("+selection+')');
			break;
		default:break;
		}
		int updateCount = db.update(MyDB.DATABASE_TABLE, values, selection, selectionArgs);
		getContext().getContentResolver().notifyChange(uri, null);
		return updateCount;
	}

	@Override
	public ParcelFileDescriptor openFile(Uri uri, String mode)
			throws FileNotFoundException {
		String rowId = uri.getPathSegments().get(1);
		File file = new File(getContext().getExternalFilesDir(Environment.DIRECTORY_PICTURES), rowId);
		if(!file.exists()){
			try {
				file.createNewFile();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		int fileMode = 0;
		if(mode.contains("w")){
			fileMode |= ParcelFileDescriptor.MODE_WRITE_ONLY;
		}
		if(mode.contains("r")){
			fileMode |= ParcelFileDescriptor.MODE_READ_ONLY;
		}
		if(mode.contains("+")){
			fileMode |= ParcelFileDescriptor.MODE_APPEND;
		}
		return ParcelFileDescriptor.open(file, fileMode);
	}
}

2) MyDB.java

public class MyDB extends SQLiteOpenHelper {
	private static final String TAG = MyDB.class.getSimpleName();

	public static final String KEY_ID = "_id";
	public static final String KEY_GOLD_HOARD_NAME_COLUMN = "GOLD_HOARD_NAME_COLUMN";
	public static final String KEY_GOLD_HOARD_ACCESSIBLE_COLUMN = "GOLD_HOARD_ACCESSIBLE_COLUMN";
	public static final String KEY_GOLD_HOARDED_COLUMN = "GOLD_HOARDED_COLUMN";
	
	public static final String DATABASE_NAME = "me.db";
	public static final String DATABASE_TABLE = "GoldHoards";
	public static final int DATABASE_VERSION = 1;
	private static final String DATABASE_CREATE = "create table " + DATABASE_TABLE + " ("
			+ KEY_ID + " integer primary key autoincrement, "
			+ KEY_GOLD_HOARD_NAME_COLUMN + " text not null, "
			+ KEY_GOLD_HOARDED_COLUMN + " float, "
			+ KEY_GOLD_HOARD_ACCESSIBLE_COLUMN + " integer);";
	
	public MyDB(Context context, String name, CursorFactory factory, int version){
		super(context, name, factory, version);
	}
	
	@Override
	public void onConfigure(SQLiteDatabase db) {
		Log.d(TAG, "onConfigure");
		//API Level 16
//		super.onConfigure(db);
	}
	
	@Override
	public void onCreate(SQLiteDatabase db) {
		Log.d(TAG, "onCreate");
		//建表
		db.execSQL(DATABASE_CREATE);
	}

	@Override
	public void onOpen(SQLiteDatabase db) {
		Log.d(TAG, "onOpen");
		super.onOpen(db);
	}
	
	@Override
	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
		Log.d(TAG, "onUpgrade");
		//删除旧表重建新表
		db.execSQL("DROP TABLE IF EXISTS "+DATABASE_TABLE);
		onCreate(db);
	}

	@Override
	public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
		Log.d(TAG, "onDowngrade");
		//API Level 11
//		super.onDowngrade(db, oldVersion, newVersion);
		db.execSQL("DROP TABLE IF EXISTS "+DATABASE_TABLE);
		onCreate(db);
	}
}

3) MainActivity.java

public class MainActivity extends Activity {
	private static final String TAG = MainActivity.class.getSimpleName();
	MyDB myDB;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		Log.d(TAG, "onCreate");
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		myDB = new MyDB(getApplication(), MyDB.DATABASE_NAME, null, MyDB.DATABASE_VERSION);
	}
	public void onClick(View v){
		SQLiteDatabase database;
		switch(v.getId()){
		case R.id.btn_insert:
			ContentValues contentValues = new ContentValues();
			contentValues.put(MyDB.KEY_GOLD_HOARD_NAME_COLUMN, "gold mountain");
			contentValues.put(MyDB.KEY_GOLD_HOARDED_COLUMN, 5.2f);
			contentValues.put(MyDB.KEY_GOLD_HOARD_ACCESSIBLE_COLUMN, 1);
			database = myDB.getWritableDatabase();
			database.insert(MyDB.DATABASE_TABLE, null, contentValues);
			database.releaseReference();//equivalent to Closable.close()
			break;
		case R.id.btn_query:
			String[] result_columns = {MyDB.KEY_ID,MyDB.KEY_GOLD_HOARD_NAME_COLUMN,MyDB.KEY_GOLD_HOARDED_COLUMN,
					MyDB.KEY_GOLD_HOARD_ACCESSIBLE_COLUMN};
			String where = MyDB.KEY_GOLD_HOARD_ACCESSIBLE_COLUMN + "=" +1;
			database = myDB.getWritableDatabase();
			Cursor cursor = database.query(MyDB.DATABASE_TABLE, result_columns, where, null, null, null, null, null);
			StringBuilder sb = new StringBuilder();
			while(cursor.moveToNext()){
				sb.append(cursor.getInt(cursor.getColumnIndexOrThrow(MyDB.KEY_ID))).append(',')
					.append(cursor.getString(cursor.getColumnIndexOrThrow(MyDB.KEY_GOLD_HOARD_NAME_COLUMN))).append(',')
					.append(cursor.getFloat(cursor.getColumnIndexOrThrow(MyDB.KEY_GOLD_HOARDED_COLUMN))).append(',')
					.append(cursor.getInt(cursor.getColumnIndexOrThrow(MyDB.KEY_GOLD_HOARD_ACCESSIBLE_COLUMN))).append('\n');
			}
			cursor.close();
			database.releaseReference();
			if(sb.length()>0){
				sb.deleteCharAt(sb.length()-1);
				Toast.makeText(this, sb, Toast.LENGTH_SHORT).show();
			}
			break;
		case R.id.btn_update:
			ContentValues newValues = new ContentValues();
			newValues.put(MyDB.KEY_GOLD_HOARD_NAME_COLUMN, "silver");
			newValues.put(MyDB.KEY_GOLD_HOARDED_COLUMN, 3.1f);
			String whereU = MyDB.KEY_ID + "=" +1;
			database = myDB.getWritableDatabase();
			//更新指定行指定列数据
			database.update(MyDB.DATABASE_TABLE, newValues, whereU, null);
			database.close();
			break;
		case R.id.btn_delete:
			String whereR = MyDB.KEY_ID + "=" + 1;
			database = myDB.getWritableDatabase();
			//删除指定行数据
			database.delete(MyDB.DATABASE_TABLE, whereR, null);
			database.close();
			break;
		case R.id.btn_drop:
			database = myDB.getWritableDatabase();
			//清空表中数据
			database.delete(MyDB.DATABASE_TABLE, null, null);
			database.close();
			break;
		case R.id.btn_queryItem:
			queryItem();
			break;
		case R.id.btn_queryItems:
			queryContent();
		}
	}
	//查询指定范围的数据
	private void queryContent(){
		ContentResolver contentResolver = getContentResolver();
		String[] resultColumns = {MyDB.KEY_ID, MyDB.KEY_GOLD_HOARD_NAME_COLUMN, 
				MyDB.KEY_GOLD_HOARDED_COLUMN, MyDB.KEY_GOLD_HOARD_ACCESSIBLE_COLUMN};
		String where = MyDB.KEY_GOLD_HOARD_ACCESSIBLE_COLUMN +"="+1;
		Cursor cursor = contentResolver.query(MyContentProvider.CONTENT_URI, resultColumns, where, null, null);
		StringBuilder sb = new StringBuilder();
		while(cursor.moveToNext()){
			sb.append(cursor.getString(cursor.getColumnIndexOrThrow(MyDB.KEY_GOLD_HOARD_NAME_COLUMN))).append(',')
				.append(cursor.getFloat(cursor.getColumnIndexOrThrow(MyDB.KEY_GOLD_HOARDED_COLUMN))).append('\n');
		}
		if(sb.length()>0){
			sb.deleteCharAt(sb.length()-1);
			Toast.makeText(this, sb, Toast.LENGTH_SHORT).show();
		}
	}
	//查询单行数据
	private void queryItem(){
		ContentResolver contentResolver = getContentResolver();
		String[] resultColumns = {MyDB.KEY_ID, MyDB.KEY_GOLD_HOARD_NAME_COLUMN, 
				MyDB.KEY_GOLD_HOARDED_COLUMN, MyDB.KEY_GOLD_HOARD_ACCESSIBLE_COLUMN};
		//指定行,不再需要where
		Uri rowAddress = ContentUris.withAppendedId(MyContentProvider.CONTENT_URI, 2);
		Cursor cursor = contentResolver.query(rowAddress, resultColumns, null, null, null);
		StringBuilder sb = new StringBuilder();
		while(cursor.moveToNext()){
			sb.append(cursor.getString(cursor.getColumnIndexOrThrow(MyDB.KEY_GOLD_HOARD_NAME_COLUMN))).append(',')
				.append(cursor.getFloat(cursor.getColumnIndexOrThrow(MyDB.KEY_GOLD_HOARDED_COLUMN))).append('\n');
		}
		if(sb.length()>0){
			sb.deleteCharAt(sb.length()-1);
			Toast.makeText(this, sb, Toast.LENGTH_SHORT).show();
		}
	}
}

4) activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    xmlns:android="http://schemas.android.com/apk/res/android">
    <Button 
        android:id="@+id/btn_insert"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="insert"
        android:onClick="onClick"/>
    <Button 
        android:id="@+id/btn_query"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="query"
        android:onClick="onClick"/>
    <Button 
        android:id="@+id/btn_update"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="update"
        android:onClick="onClick"/>
    <Button 
        android:id="@+id/btn_delete"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="delete"
        android:onClick="onClick"/>
    <Button 
        android:id="@+id/btn_drop"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="drop"
        android:onClick="onClick"/>
    <Button 
        android:id="@+id/btn_queryItem"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="queryItem"
        android:onClick="onClick"/>
    <Button 
        android:id="@+id/btn_queryItems"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="queryItems"
        android:onClick="onClick"/>
</LinearLayout>

5) AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.qinuli.mycontentprovider"
    android:versionCode="1"
    android:versionName="1.0" >

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

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <!-- APP启动时自动启动 -->
        <activity android:name="com.qinuli.mycontentprovider.MainActivity"
            android:launchMode="singleTop">
            <intent-filter >
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <provider 
            android:name="com.qinuli.mycontentprovider.MyContentProvider"
            android:authorities="com.qinuli.provider.mycontentprovider"></provider>
    </application>

</manifest>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值