android中ContentProvider学习心得
2015-06-05 20:43
399 查看
ContentProvider-内容提供者是android中四大组件之一,可见是比较重要的。他可以在不同app之间(进程之间)提供数据共享,且可以进行增删改查,当然在自己进程里也同样可以的。要实现数据共享,必定离不开ContentResolver-内容解决者。ContentProvider内部实现了增删改查的方法,并向外提供了若干个URI;ContentResolver也有增删改查方法,各方法都需传入URI,通过URI就可以找到正确的ContentProvider,并执行对应的方法。
自定义内容提供者,需继承ContentProvider抽象类,并重写增删改查方法,其中数据需要保存到数据库中,必定需要用到SQLite数据库,android创建数据库一般都用SQLiteOpenHelper。以下是测试代码,TestContentProvider.java:
android四大组件都需要在AndroidManifest.xml中注册,当然ContentProvider也不例外。
内容解决者可以对感兴趣的内容提供者进行监听,当有数据发生改变时,可以收到通知,当然了这需要内容提供者发送通知才行 getContext().getContentResolver().notifyChange(uri, null);
注册收到通知代码如下:
内容解决者可以访问内容提供者暴露出来的URI,进行数据共享操作。在Activity中获取ContentResolver:
批量操作的话,可以使用操作列表:
自定义内容提供者,需继承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(); } }
相关文章推荐
- Android中通过xml改变背景及文字颜色
- Android的R文件
- Android Wear Step Sensor
- Android 文件目录学习 src,gen,asssts,res是嘛用的?
- udacity android 学习笔记: lesson 4 part b
- Android如何在非Activity类中实现Vibrate效果
- Android ART runtime简述
- Android SDK Manager 更新
- 太白---落燕纷飞第一重 Android单元测试Instrumentation和irobotium
- android中利用自定义View中的onTouchEvent捕捉长按事件
- android桌面壁纸不滑动
- android中 回调方法,怎么转变为阻塞执行的方法
- Activity的生命周期
- 初涉Android蓝牙开发
- 预置第三方apk到MTK项目相关问题总结
- android Android-PullToRefresh 下拉刷新
- android桌面快捷方式跳转到指定activity
- android 融云 集成遇到的问题集锦
- android 之EditText输入检测
- android 里的receiver 就像一个实时监控 总线数据,或者消息(intent)队列的东西,回调函数类似