美文网首页Android知识Android技术知识Android开发
Android开发:ContentProvider实例详解

Android开发:ContentProvider实例详解

作者: Gunther | 来源:发表于2016-12-13 14:58 被阅读757次
  • 2016年12月8日,Google中国开发者大会在京举行,同时正式上线了Google中国开发者网站Google Developers,查看官方学习资源再也不用爬梯子了
  1. 简介
  2. 使用说明
  3. ContentObserver

简介

ContentProvider即内容提供者,是Android的四大组件之一。内容提供者是应用程序之间共享数据的接口,Android系统将这种机制应用到方方面面。

比如:联系人Provider专为不同应用程序提供联系人数据;设置Provider专为不同应用程序提供系统配置信息,包括内置的设置应用程序等。当应用继承ContentProvider类,并重写该类用于提供数据和存储数据的方法,就可以向其他应用共享其数据。

虽然使用其他方法也可以对外共享数据,但数据访问方式会因数据存储的方式而不同,如:采用文件方式对外共享数据,需要进行文件操作读写数据;采用SharedPreferences共享数据,需要使用SharedPreferences API读写数据。

而使用ContentProvider共享数据的好处是统一了数据访问方式。内容提供者将数据封装,只暴露出我们希望提供给其他程序的数据。内容提供者中数据更改可被监听。

使用说明

  1. 定义类继承ContentProvider,根据需要重写内部方法(增删改查)
  2. 在清单文件的<application>节点下进行配置,<provider>标签中需要指定name和authorities属性
    name:类名,包名从程序Package开始,以“.”开始
    authorities:是访问Provider时的路径,要唯一
  3. URI代表要操作的数据,由scheme、authorites、path三部分组成
    content://cn.gunther.sqlite.provider/person
    scheme:固定为content,代表访问内容提供者
    authorites:<provider>节点中的authorites属性
    path:程序定义的路径,可根据业务逻辑定义

示例代码:

  1. 新建一个工程MyContentProvider,包名:com.gunther.provider。
  2. 在com.gunther.provider.dao包下新建PersonOpenHelper类继承SQLiteOpenHelper类,该类用于创建数据库。
    public class PersonOpenHelper extends SQLiteOpenHelper {

    public PersonOpenHelper(Context context, String name, CursorFactory factory, int version) {
        super(context, name, factory, version);
    }
    
    public PersonOpenHelper(Context context){
        super(context, "person.db", null, 1);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        String sql = "create table person (id integer primary key autoincrement,name varchar(20),phone varchar(20),age integer,address varchar(50));";
        db.execSQL(sql);

    }

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

    }

    }
  1. 在com.gunther.contenProvider.provider包中创建,PersonContentProvider类继承ContentProvider类。同时将该Provider在AndroidManifest.xml中注册。

    <provider    android:exported="true"     
    android:name="com.gunther.contenProvider.provider.PersonContentProvider"
    android:authorities="com.gunther.person" />
    
    
    
    
     public class PersonContentProvider extends ContentProvider {
     //用于存放并匹配个Uri标识信息,一般在静态代码块中对其信息进行初始化操作
     private static UriMatcher matcher;
     //声明一个用于操作数据库对象
     private PersonOpenHelper openHelper;
     //主机名信息:对应清单文件的authorities属性
     private static final String AUTHORITY = "com.gunther.person";
     //数据库 表名
     private static final String TABLE_PERSON_NAME = "person";
     //Uri匹配成功的返回码
     private static final int PERSON_INSERT_CODE = 1000;
     private static final int PERSON_DELETE_CODE = 10001;
     private static final int PERSON_UPDATE_CODE = 10002;
     private static final int PERSON_QUERYALL_CODE = 10003;
     private static final int PERSON_QUERYONE_CODE = 10004;
     //静态代码块,用于初始化UriMatcher
     static{
         //NO_MATCH:没有Uri匹配的时候返回的状态码(-1)
         matcher = new UriMatcher(UriMatcher.NO_MATCH);
         //添加一个分机号:
         //对person表进行添加操作,如果Uri=content://com.gunther.person/person/insert,则返回PERSON_INSERT_CODE
         matcher.addURI(AUTHORITY, "person/insert", PERSON_INSERT_CODE);
         //对person表进行删除操作,如果Uri= content://com.gunther.person/person/delete,则返回PERSON_DELETE_CODE
         matcher.addURI(AUTHORITY, "person/delete", PERSON_DELETE_CODE);
         //对person表进行修改操作,如果Uri= content://com.gunther.person/person/update,则返回PERSON_UPDATE_CODE
         matcher.addURI(AUTHORITY, "person/update", PERSON_UPDATE_CODE);
         //对person表进行查询所有操作,如果Uri= content://com.gunther.person/person,则返回PERSON_QUERYALL_CODE
         matcher.addURI(AUTHORITY, "person", PERSON_QUERYALL_CODE);
         //对person表进行查询单个操作,如果Uri= content://com.gunther.person/person/#,(#:代表数字)则返回PERSON_QUERYONE_CODE
         matcher.addURI(AUTHORITY, "person/#", PERSON_QUERYONE_CODE);
     }
     @Override
     public boolean onCreate() {
     //内容提供者中,获取contenxt,是通过getContext,与测试类一样,不能再成员变量,构造函数中调用,但是可以再onCreate方法中获取。
         openHelper = new PersonOpenHelper(getContext());
         return false;
     }
     @Override
     public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
         //用匹配器去匹配uri,如果匹配成功则返回匹配器中对应的状态码
         int matchCode = matcher.match(uri);
         SQLiteDatabase db = openHelper.getReadableDatabase();
         switch (matchCode) {
         case PERSON_QUERYALL_CODE:
             return db.query(TABLE_PERSON_NAME, projection, selection, selectionArgs, null, null, sortOrder);
         case PERSON_QUERYONE_CODE:
     //使用ContentUris工具类解析出uri中的id
             long parseId = ContentUris.parseId(uri);
             return db.query(TABLE_PERSON_NAME, projection,"id=?", new String[]{parseId+""}, null, null, sortOrder);
         default:
             throw new IllegalArgumentException("Uri匹配失败:"+uri);
         }}
     @Override
     public Uri insert(Uri uri, ContentValues values) {
         SQLiteDatabase db = openHelper.getWritableDatabase();
         //新插入对象的id
         long id = db.insert(TABLE_PERSON_NAME, null, values);
         db.close();
         //使用ContentUris工具类将id追加到uri中,返回给客户
         return ContentUris.withAppendedId(uri, id);
     }
    
     @Override
     public int delete(Uri uri, String selection, String[] selectionArgs) {
         SQLiteDatabase db = openHelper.getWritableDatabase();
         //返回删除的个数
         int count = db.delete(TABLE_PERSON_NAME, selection, selectionArgs);
         //关闭数据库
         db.close();
         return count;
     }
    
     @Override
     public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
         SQLiteDatabase db = openHelper.getWritableDatabase();
         //返回更新的个数
         int count = db.update(TABLE_PERSON_NAME, values, selection, selectionArgs);
         //更新数据库
         db.close();
         return count;
     }
    
     @Override
     public String getType(Uri uri) {
         return null;
     }
    
     }
    

ContentObserver

ContentObserver——内容观察者,目的是观察(捕捉)特定Uri引起的数据库的变化,继而做一些相应的处理,它类似于数据库技术中的触发器(Trigger),当ContentObserver所观察的Uri发生变化时,便会触发它。触发器分为表触发器、行触发器,相应地ContentObserver也分为“表“ContentObserver、“行”ContentObserver,当然这是与它所监听的Uri MIME Type有关的。

private class AppLockObserver extends ContentObserver{
    public AppLockObserver(){
        super(new Handler());
    }
    @Override
    public void onChange(boolean selfChange) {
        super.onChange(selfChange);
        //观察到注册的uri数据发送变化,根据业务需求处理
    }
}

相关文章

网友评论

    本文标题:Android开发:ContentProvider实例详解

    本文链接:https://www.haomeiwen.com/subject/zuqbmttx.html