您的位置:首页 > 移动开发 > Android开发

android中ContentProvider学习心得

2015-06-05 20:43 399 查看
ContentProvider-内容提供者是android中四大组件之一,可见是比较重要的。他可以在不同app之间(进程之间)提供数据共享,且可以进行增删改查,当然在自己进程里也同样可以的。要实现数据共享,必定离不开ContentResolver-内容解决者。ContentProvider内部实现了增删改查的方法,并向外提供了若干个URI;ContentResolver也有增删改查方法,各方法都需传入URI,通过URI就可以找到正确的ContentProvider,并执行对应的方法。

自定义内容提供者,需继承ContentProvider抽象类,并重写增删改查方法,其中数据需要保存到数据库中,必定需要用到SQLite数据库,android创建数据库一般都用SQLiteOpenHelper。以下是测试代码,TestContentProvider.java:

package com.test.contprovider;

import java.util.ArrayList;

import android.content.ContentProvider;
import android.content.ContentProviderOperation;
import android.content.ContentProviderResult;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.OperationApplicationException;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
import android.net.Uri;
import android.text.TextUtils;

public class TestContentProvider extends ContentProvider {

/*外部通过这个类拿URI及相关字段等常量*/
public static class TestWords{

/*内容提供者主机头,全局唯一,要跟AndroidMainifast.xml注册的一致*/
public static final String AUTHORITY = "com.test.content.provider";

/*外部调用时的URI*/
public static final Uri CONTENT_ALL_URI = Uri.parse("content://"+AUTHORITY+"/all");
public static final Uri CONTENT_ONE_URI = Uri.parse("content://"+AUTHORITY+"/one");

/*数据库表字段*/
public static final String COLUMN_ID = "_id";
public static final String COLUMN_WORD = "word";

}

private TestSQLiteOpenHelper sqlhelper;
private String TABLE = "words";

/*URI匹配器,检查外部调用的是哪个URI*/
private static UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
private static int ALL = 1;
private static int ONE = 2;

static{
matcher.addURI(TestWords.AUTHORITY, "all", ALL);
/* ‘#’号代表可以是任意数字,通常是_id字段值 */
matcher.addURI(TestWords.AUTHORITY, "one/#", ONE);
}

@Override
public boolean onCreate() {
/*创建数据库words.db*/
sqlhelper = new TestSQLiteOpenHelper(getContext(), "words.db", null,1);

return true ;
}

@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
SQLiteDatabase db
= sqlhelper.getWritableDatabase();

//匹配uri
if(matcher.match(uri)==ALL){
return db.query(TABLE, projection, selection, selectionArgs, null, null, sortOrder);
}else if(matcher.match(uri)==ONE){
long _id = ContentUris.parseId(uri);
//设置查询条件
String where = TestWords.COLUMN_ID +"=" + _id + " ";
if(!TextUtils.isEmpty(selection)){
where+=selection;
}
return db.query(TABLE, projection, where, selectionArgs, null, null, sortOrder);

}
return null;
}

@Override
public String getType(Uri uri) {
//…………
return null;
}

@Override
public Uri insert(Uri uri, ContentValues values) {
SQLiteDatabase db = sqlhelper.getWritableDatabase();
long _id = db.insert(TABLE, "_id", values);
if(_id>0){
uri = ContentUris.withAppendedId(uri, _id);
//通知内容解决者,数据发生改变
getContext().getContentResolver().notifyChange(uri, null);
return uri;
}
return null;
}

@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
//…………
return 0;
}

@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
//…………
return 0;
}

/*批量更新,可以提高执行效率,可以跟进源码父类applyBatch方法没有进行事务处理
*为了保正操作一致性,可以重写该方法,加上事务处理
*/
@Override
public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations)
throws OperationApplicationException{
SQLiteDatabase db = sqlhelper.getWritableDatabase();
//开始事务
db.beginTransaction();
try{
ContentProviderResult[] results = super.applyBatch(operations);
//设置事务标记为successful
db.setTransactionSuccessful();
return results;
}finally {
//结束事务
db.endTransaction();
}
}

public class TestSQLiteOpenHelper extends SQLiteOpenHelper{

public TestSQLiteOpenHelper(Context context, String name,
CursorFactory factory, int version) {
super(context, name, factory, version);

}

@Override
public void onCreate(SQLiteDatabase db) {
/*创建表words,字段两个:_id , word */
String sql = "create table words(_id integer primary key autoincrement,word text) ";
db.execSQL(sql);
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

}

}

}


android四大组件都需要在AndroidManifest.xml中注册,当然ContentProvider也不例外。

<provider android:name=".TestContentProvider" 
            android:authorities="com.test.content.provider" >
        </provider>
简单的注册如上就可以了。当然了注册时还牵涉到访问权限的问题,还需待进一步研究。

内容解决者可以对感兴趣的内容提供者进行监听,当有数据发生改变时,可以收到通知,当然了这需要内容提供者发送通知才行 getContext().getContentResolver().notifyChange(uri, null);

注册收到通知代码如下:

getContentResolver().registerContentObserver(
TestWords.CONTENT_ONE_URI, true,
new ContentObserver(handler) {

@Override
public boolean deliverSelfNotifications() {
System.out.println("--------deliverSelfNotification-----");
return super.deliverSelfNotifications();
}

@Override
public void onChange(boolean selfChange) {
System.out.println("--------onChange-----"+selfChange);
super.onChange(selfChange);
}

@Override
public void onChange(boolean selfChange, Uri uri) {
super.onChange(selfChange, uri);
System.out.println("--------onChange-----"+selfChange+","+uri);
}

});


内容解决者可以访问内容提供者暴露出来的URI,进行数据共享操作。在Activity中获取ContentResolver:

ContentResolver cr = getContentResolver();
/*非自己进程写入URI*/
//Uri uri = Uri.parse("content://com.test.content.provider/all");
/*自己进程中获取URI*/
Uri uri = TestWords.CONTENT_ALL_URI;

Cursor cursor = cr.query(uri, null,  null, null, null);


批量操作的话,可以使用操作列表:

void batchAdd(){
ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();

ops.add(ContentProviderOperation.newInsert(TestWords.CONTENT_ONE_URI)
.withValue(TestWords.COLUMN_WORD, "one")
.build());
ops.add(ContentProviderOperation.newInsert(TestWords.CONTENT_ONE_URI)
.withValue(TestWords.COLUMN_WORD, "two")
.build());
ops.add(ContentProviderOperation.newInsert(TestWords.CONTENT_ONE_URI)
.withValue(TestWords.COLUMN_WORD, "three")
.build());

ContentResolver cr = getContentResolver();
try {
ContentProviderResult[] cpr = cr.applyBatch(TestWords.AUTHORITY, ops);

} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (OperationApplicationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: