对数据库的操作,我们经常避免不了进行事务处理,这样可以减少对数据库操作的次数,从而提高了读写数据库的效率。之前博主对ContentProvider基本使用和涉及的知识点有个大致的概括,这里就不详叙了,今天主要说一下如何使用ContentProvider处理事务以及对数据库的表进行监控。
一、通过ContentProvider实现对数据库进行批处理
我们知道一般对数据库操作有两种方式,一种使用封装好的ContentProvider给外部(其他进程或者对象)进行数据库操作,另外一种直接通过SQLiteDatabase执行sql语句,达到对数据库增删改查效果。
如在使用SQLiteDatabase进行数据库操作的时候
DatabaseHelper dbhelper = new DatabaseHelper(ctx);
SQLiteDatabase db =dbhelper.getWritableDatabase();
StringBuffer sb = new StringBuffer();
sb.append("CREATE TABLE IF NOT EXISTS ");
sb.append(DvbNetworkDatabase.TransportStreams.TABLE_NAME);
sb.append(" (");
sb.append(TransportStreams._ID).append(" INTEGER PRIMARY KEY,");
sb.append(TransportStreams.FREQUENCY).append(" INT,");
sb.append(TransportStreams.DEVLIVERY_TYPE).append(" INT,");
sb.append(TransportStreams.TRANSPORT_STREAM_ID).append(" INT,");
sb.append(TransportStreams.MPEG_TRANSPORT_STREAM_ID).append(" INT,");
sb.append(TransportStreams.NETWORK_ID).append(" INT,");
sb.append(TransportStreams.ORIGINAL_NETWORK_ID).append(" INT,");
sb.append(TransportStreams.INFO_VERSION).append(" INT,");
sb.append(TransportStreams.TUNE_PARAM).append(" TEXT);");
createTSTableSql = sb.toString();
db.execSQL(createTSTableSql);
使用SQLiteDatabase实现事务批处理
SQLiteDatabase db =mOpenHelper.getWritableDatabase();
db.beginTransaction();//开始事务
//进行insertdelete update等数据库操作
db.setTransactionSuccessful();//设置事务标记为Successful
db.endTransaction();//提交事务
在使用SQLiteDatabase对数据库操作,我们一般都是在应用里面(同一个进程下)实现的,现在通过ContentProvider对外接口,我们如何实现呢?我们可以翻一下官网文档或者查看一下源码发现有一个applyBatch的方法,Override this to handle requests to perform a batch of operations(重写此处理请求执行批量操作)
public ContentProviderResult[] applyBatch(ArrayList operations)
throws OperationApplicationException {
SQLiteDatabase db = mDatabaseHelper.getWritableDatabase();
db.beginTransaction();// 开始事务
try {
ContentProviderResult[] results = super.applyBatch(operations);
db.setTransactionSuccessful();// 设置事务标记为successful
return results;
} finally {
db.endTransaction();// 结束事务
Uri uri = null;
for (ContentProviderOperation opt : operations) {
if (opt.getUri().equals(uri)) {
continue;
}
uri = opt.getUri();
getContext().getContentResolver().notifyChange(opt.getUri(), null);
Log.i(TAG, "notifychange endTransaction..uri:" + opt.getUri());
}
}
}
当我们通过ContentProvider执行批处理时如下方法
ArrayList ops = new ArrayList();
//删除操作
String[] args = new String[] { String.valueOf(GROUP_ID), String.valueOf(USER_ID) };
ops.add(ContentProviderOperation.newDelete(uri).withSelection(DEL_SELECTTION, args)
.build());
//增加操作 value为ContentValue
ops.add(ContentProviderOperation.newInsert(uri).withValues(value).build());
//修改操作
……newUpdate……
二、通过ContentObserver实现对数据库表进行监控
通常我们对某一个数据进行监控,都会去创建一个线程达到对数据监控的效果,这样做对cpu占用率和内存开销是很大的,在对数据库表进行监控,android提供了一套完善的机制,使用ContentProvider。ContentObserver——内容观察者,目的是观察(捕捉)特定Uri引起的数据库的变化,继而做一些相应的处理,它类似于数据库技术中的触发器(Trigger),当ContentObserver所观察的Uri发生变化时,便会触发它。触发器分为,表触发器、行触发器,相应地ContentObserver也分为“表“ContentObserver、“行”ContentObserver,当然这是与它所监听的Uri MIME Type有关的。通过ContentObserver对数据库表/行进行监控,我们需要实现下面三个步骤:
1、创建我们特定的ContentObserver派生类,必须重载onChange()方法去处理回调后的功能实现
2、利用context.getContentResolover()获得ContentResolove对象,接着调用registerContentObserver()方法去注册内容观察者,为指定的Uri注册一个ContentObserver派生类实例,当给定的Uri发生改变时,回调该实例对象去处理。
3、由于ContentObserver的生命周期不同步于Activity和Service等,因此,在不需要时,需要手动的调用unregisterContentObserver()去取消注册。
public ContentObserver setChannelObserver(){
channelObserver = new ContentObserver(channelHandler) {
public void onChange(boolean selfChange) {
Log.i("3--3", "--------------go in Observe channelObserver");
postLoadChannels();
};
};
return channelObserver;
}
……
context.getContentResolver().registerContentObserver(channelsUri, false,
setChannelObserver());
……