ContentProvider & ContentResolver & ContentObserver
来源:互联网 发布:知世故而不世故谁写的 编辑:程序博客网 时间:2024/05/22 01:09
作用:暴露应用的数据。可以获取不同应用的数据。
/data/data/应用包/databases/xxx.db
2.创建一个类继承Provider
Provider自身方法: onCreate query insert delete update getType --- 必须要重写
Provider要访问本应用数据库,需要在Provider中创建一个SQLiteOpenHelper,并且在onCreate方法中实例化。
然后再每个要执行数据库操作方法中(query insert delete update)通过helper打开数据库并使用数据库相应方法。
Cursor query(...) 查询返回值为Cursor,即查询内容都在Cursor中
Uri insert(...) 返回新添加数据的uri
int update(...) 返回更新操作影响的行数
int delete(...) 返回删除操作影响的行数
其原理就是在Provider中保存一个SQLiteOpneHelper,通过helper得到SQLiteDatabase。
然后在其增删改查的方法中,调用database的相应的增删改查方法。
3.在清单中注册
四大组件之一,要注册。
注册时,需要类名与权限(android:authorities),权限即为对外暴露的访问该提供者的标示
当应用程序启动,会自动创建内容提供者。
4.访问内容提供者,使用ContentResolver
ContentResolver resolver = getContentResolver();
Resolver方法:query insert delete update
5.Uri
1)Uri格式:content://主机名或authority/路径(路径中可包含ID)
content://com.itheima/person/1
Uri.parse("uri...")
注意:操作ID要使用类ContentUris,见后。
2)安卓自身的Uri以及表字段,都有对应的常量。
联系人Uri常量:Calls.CONTENT_URI;
联系人通话记录表中字段Calls.NUMBER --- 电话号码,Calls.DURATION --- 通话时长, Calls._ID --- ID号。
多媒体Uri常量:(andrdroid.provider.MediaStore.Audio.)Media.EXTERNAL_CONTENT_URI --- 访问音频外部存储的Uri
(andrdroid.provider.MediaStore.Audio.)Media.INTERNAL_CONTENT_URI --- 访问音频手机内存的Uri
(android.provider.MediaStore.Images.)Media.EXTERNAL_CONTENT_URI / Media.INTERNAL_CONTENT_URI 图像
(android.provider.MediaStore.Video.)Media.EXTERNAL_CONTENT_URI / Media.INTERNAL_CONTENT_URI 视频
多媒体表字段: Media._ID; ID号 Media.DISPLAY_NAME 名称 Media.SIZE 大小
6.在内容提供者里面定义一组Uri
UriMatcher
方法:addURI(authority, path, code);
如:
matcher.addURI(authority, path, code);
参数:
authority即为清单中provider的authority
code为匹配码,即该uri对应的唯一码,matcher.match(uri)的返回值
matcher.addURI(authority, "m", 1000);
matcher.addURI(authority, "m/#", 1000);
注:#代表数字, *代表字符
代码:
class MyProvider extends ContentProvider{//authority即为清单中注册的authorityprivate static final String authority = "...";private static UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH); static{ matcher.addURI(authority, "...", code); } }
match方法
7.ContentUris
该类用于获取Uri路径后面的ID部分,也可以为Uri路径加上ID部分。
添加ID -- withAppendId()
Uri uri = Uri.parse("content://....");
Uri resultUri = ContentUris.withAppendId(uri, 10);
获取ID -- parseId()
Uri uri = Uri.parse("content://..../10");
long personId = ContentUris.parseId(uri);
示例:一个应用访问另一个应用的数据库。
Provider应用
public class MyProvider extends ContentProvider {private MyOpenHelper helper;private static final int MM = 10;private static final int MM_ID = 100;// 表名private String table = "mm";private static UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);// 与清单provider的authority一致private static String authority = "yp";static {// content://yp/mmmatcher.addURI(authority, "mm", MM);// content://yp/mm/1matcher.addURI(authority, "mm/#", MM_ID);}@Overridepublic boolean onCreate() {helper = MyOpenHelper.getInstance(getContext());return false;}/** * 查询 */@Overridepublic Cursor query(Uri uri, String[] projection, String selection,String[] selectionArgs, String sortOrder) {SQLiteDatabase db = helper.getReadableDatabase();// 获得uri匹配码int code = matcher.match(uri);Cursor cursor = null;// 通过判断匹配码,根据不同的uri做不同的操作switch (code) {// uri中没有带指定的idcase MM:// select * form mm where name = xxxcursor = db.query(table, new String[] { "*" }, selection,selectionArgs, null, null, null);break;// uri中带有指定的idcase MM_ID:// 获取指定的idlong id = ContentUris.parseId(uri);// 判断对方是否包含查询条件if (selection == null) {// 如果不包含查询条件selection = "_id = ?";selectionArgs = new String[] { id + "" };} else {// 如果包含查询条件,将id条件拼接// select * from mm where name = xxx and id = xxselection = selection + " and _id = " + id;}cursor = db.query(table, new String[] { "*" }, selection,selectionArgs, null, null, null);break;default:break;}// 数据库不可以关闭return cursor;}/** * 插入 */@Overridepublic Uri insert(Uri uri, ContentValues values) {SQLiteDatabase db = helper.getWritableDatabase();long id = db.insert(table, "_id", values);return ContentUris.withAppendedId(uri, id);}/** * 更新 */@Overridepublic int update(Uri uri, ContentValues values, String selection,String[] selectionArgs) {SQLiteDatabase db = helper.getReadableDatabase();// 获得uri匹配码int code = matcher.match(uri);int rows = 0;// 通过判断匹配码,根据不同的uri做不同的操作switch (code) {// uri中没有带指定的idcase MM:rows = db.update(table, values, selection, selectionArgs);break;// uri中带有指定的idcase MM_ID:// 获取指定的idlong id = ContentUris.parseId(uri);// 判断对方是否包含查询条件if (selection == null) {// 如果不包含查询条件selection = "_id = ?";selectionArgs = new String[] { id + "" };} else {// 如果包含查询条件,将id条件拼接selection = selection + " and _id = " + id;}rows = db.update(table, values, selection, selectionArgs);break;default:break;}return rows;}/** * 删除 */@Overridepublic int delete(Uri uri, String selection, String[] selectionArgs) {SQLiteDatabase db = helper.getReadableDatabase();// 获得uri匹配码int code = matcher.match(uri);int ret = 0;// 通过判断匹配码,根据不同的uri做不同的操作switch (code) {// uri中没有带指定的idcase MM:db.delete(table, selection, selectionArgs);break;// uri中带有指定的idcase MM_ID:// 获取指定的idlong id = ContentUris.parseId(uri);// 判断对方是否包含查询条件if (selection == null) {// 如果不包含查询条件selection = "_id = ?";selectionArgs = new String[] { id + "" };} else {// 如果包含查询条件,将id条件拼接selection = selection + " and _id = " + id;}ret = db.delete(table, selection, selectionArgs);break;default:break;}return ret;}@Overridepublic String getType(Uri uri) {return null;}}
Resolver应用
public class MainActivity extends Activity {private ContentResolver resolver;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);resolver = getContentResolver();}public void click(View v) {ContentValues values = new ContentValues();switch (v.getId()) {case R.id.insert:values.clear();values.put("name", "ly");values.put("age", 20);resolver.insert(Uri.parse("content://yp/mm"), values);break;case R.id.update:values.clear();values.put("name", "yl");values.put("age", 18);resolver.update(Uri.parse("content://yp/mm/10"), values, null, null);break;case R.id.delete:resolver.delete(Uri.parse("content://yp/mm"), "name = ?",new String[] { "yl" });break;case R.id.query:Cursor cursor = resolver.query(Uri.parse("content://yp/mm"),new String[] { "*" }, null, null, null);while (cursor.moveToNext()) {int _id = cursor.getInt(0);String name = cursor.getString(1);int age = cursor.getInt(2);System.out.println("_id = " + _id + " name = " + name+ " age = " + age);}cursor.close();break;default:break;}}}
8.UriMatcher与ContentUris
UriMatcher.match()方法与ContentUris.withAppendId/parseId方法区别。
一条uri: "content://ly/mm/10"
使用UriMatcher.addURI()方法:matcher.addURI(authority, "mm", 100); 是将这条URI独一无二的分配100标识码。即后面使用matcher.match(uri);的返回值如果是100,那么当前uri就是 "content://ly/mm/10"。
而ContentUris操作的是uri最后的 '10' ,即向uri最后插入数字或者获取uri最后的数字。
9.ContentObserver
内容观察者,观察内容提供者数据的变化。如果内容提供者数据变化了,那么发送信息给观察者。
原理:在resolver身上注册一个观察者observer,当数据改变时,调用观察者的onChange方法
在provider的数据会发生改变的方法中调用resolver的notifyChange方法。
1) 在Provider中数据改变要通知的某方法内(如insert)
getContext().getContentProvider().nofityChange(uri, observer);
例:getContext().getContentProvider().nofityChange(uri, null);
2) 在数据改变时需要被通知的类中,写一个内部类继承ContentObserver。
并实现构造方法和onChange(boolean selfChange)方法。数据发生改变时,onChange方法被调用
3) 在该类中注册观察者
resolver.registerContentObserver(uri, notifyForDescendents, observer);
第二个参数为boolean类型的值,表示是否级联。
如:uri为 content://yp/mm 那么content://yp/mm/10发生变化时是否通知。
例:resolver.registerContentObserver(uri, false, observer);
Provider
/** * 插入 */@Overridepublic Uri insert(Uri uri, ContentValues values) {//数据改变时发出通知getContext().getContentResolver().notifyChange(uri, null);SQLiteDatabase db = helper.getWritableDatabase();long id = db.insert(table, "_id", values);return ContentUris.withAppendedId(uri, id);}
LApp
public class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);ContentResolver resolver = getContentResolver();MyObserver observer = new MyObserver(new Handler());// 注册观察者resolver.registerContentObserver(Uri.parse("content://yp/mm"), false,observer);System.out.println("内容观察者已经注册");}private class MyObserver extends ContentObserver {public MyObserver(Handler handler) {super(handler);}@Overridepublic void onChange(boolean selfChange) {super.onChange(selfChange);System.out.println("数据已经发生改变!!!");}}}
- ContentProvider、ContentValues、ContentResolver、ContentObserver
- ContentProvider & ContentResolver & ContentObserver
- ContentProvider ,ContentObserver 和ContentResolver
- Android ContentProvider、ContentResolver和ContentObserver的使用
- Android:ContentProvider、URI、UriMatcher、ContentUris、ContentResolver、ContentObserver
- ContentProvider、ContentResolver
- contentResolver and ContentProvider
- ContentProvider与ContentResolver使用
- ContentResolver与ContentProvider
- ContentProvider和ContentResolver
- ContentProvider和ContentResolver
- ContentResolver + SqliteOpenHelper + ContentProvider 理解
- ContentProvider与ContentResolver使用
- ContentProvider与ContentResolver实例
- ContentProvider与ContentResolver使用
- ContentProvider与ContentResolver使用
- 王立平--ContentResolver与ContentProvider
- android ContentResolver ContentProvider 详解
- php使用curl发送url中文乱码问题
- Session封装的线程同步
- spark报错java.lang.OutOfMemoryError: Java heap space
- Methods
- poj 2155 (二维线段树的成段更新)
- ContentProvider & ContentResolver & ContentObserver
- 【For my liz】宇宙制作全纪录(如果能成功的话TT)
- ASP.NET的内置对象:Cookie对象
- C/C++ 参数传递
- java 的浮点数计算问题
- poj 1523 求割点把一个图分成几个联通部分
- Object类中equals()方法和hashCode()方法详解
- POJ 2421 Constructing Roads(简单最小生成树)
- 104矩阵相乘