Android四大组件之ContentProvider内容提供器

ContentProvider

ContentProvider主要用于在不同的app之间实现数据共享的功能,允许一个app访问另一个app中的数据,同时保证被访数据的安全;它是实现跨程序共享数据的标准方式。

创建步骤

     继承ContentProvider类,实现其抽象方法,如:
public class MyProvider extends ContentProvider{
    
    @Override
    public boolean OnCreate(){
        /*
        初始化内容提供器时调用,一般在这里完成数据库的创建与升级等操作
        (只在有调用ContentResolver尝试访问app中的数据时,才会被初始化)
        */
        return false;//返回true代表初始化成功,false则为失败
    }
    
    @Override
    public Cursor query(Uri uri,String[] projection,String selection,
                        String[] selectionArgs,String sortOrder){
        /*
        调用该方法从内容提供器中查询数据,uri参数用作确定查询的表
        projection参数用于确定查询的列,selection,selectionArgs是查询的条件
        sortOrder是对结果进行排序
        
        查询结果存放在Cursor对象中返回
        */
        return null;
    }
    
    @Override
    public Uri insert(Uri uri,ContentValues values){
        /*
        想内容提供器中插入一条数据
        uri:确定插入的表
        values:插入的数据
        
        添加成功后会返回表示该条新数据的uri
        */
        return null;
    }
    
    @Override
    public int update(Uri uri,ContentValues values,String selection,String[] selectionArgs){
        /*
        更新数据时调用该方法
        uri:同理
        values:新的数据
        selection、selectionArgs:更新的条件
        
        返回更新了的行数
        */
        return 0;
    }
    
    @Override
    public int delete(Uri uri,String selection,String[] selectionArgs){
        /*
        删除数据时调用
        uri:同理
        selection、selectionArgs:同理
        
        返回被删除的行数
        */
        return 0;
    }
    
    @Override
    public String getType(Uri uri){
        /*
        调用该方法,是根据传入的uri返回相应的MIME类型
        */
        return null;
    }
}

    其中Uri是各个方法中必须的参数,标准的内容URI的写法为:
content://com.example.app.provider/table/id
表示的是调用com.example.app应用中table表的数据,id为查询表中 id为此值的数据(不传入此值,则代表查询全表)

若想查询匹配任意表的内容,则可将table改为 *,如:
content://com.example.app.prodiver/*

若想查询具体表中的某一行,即可将id替换为#,如:
content://com.eaxmple.app.provider/table/#

    然后,调用UriMatcher类实现匹配内容URI,调用addURI()方法,则MyProvider可修改为:
public class MyProvider extends ContentProvider{
    
    public static final int TABLE1_DIR = 0;
    public static final int TABLE1_ITEM = 1;
    public static final int TABLE2_DIR = 2;
    public static final int TABLE1_ITEM = 3;
    
    private static UriMatcher uriMatcher;
    
    static{
        uriMatcher = new UriMatcher(Uri.Matcher.NO_MATCH);
        //第一个参数为authority(一般为应用包名.provider)
        //第二个参数为path,即查询的表
        //第三个参数为自定义码
        uriMatcher.addUri("com.example.app.provider","table1",TABLE1_DIR);
        uriMatcher.addUri("com.example.app.provider","table1/#",TABLE1_ITEM);
        uriMatcher.addUri("com.example.app.provider","table2",TABLE2_DIR);
        uriMatcher.addUri("com.example.app.provider","table2/#",TABLE2_ITEM);
    }
    
    @Override
    public boolean OnCreate(){
        /*
        初始化内容提供器时调用,一般在这里完成数据库的创建与升级等操作
        (只在有调用ContentResolver尝试访问app中的数据时,才会被初始化)
        */
        return false;//返回true代表初始化成功,false则为失败
    }
    
    @Override
    public Cursor query(Uri uri,String[] projection,String selection,
                        String[] selectionArgs,String sortOrder){
        /*
        调用该方法从内容提供器中查询数据,uri参数用作确定查询的表
        projection参数用于确定查询的列,selection,selectionArgs是查询的条件
        sortOrder是对结果进行排序
        
        查询结果存放在Cursor对象中返回
        */
        //其他方法中也类似,调用uriMatcher匹配查询的位置
        switch(uriMatcher.match(uri)){
            case TABLE1_DIR:
                //查询该表的全部数据
                break;
            case TABLE1_ITEM:
                //查询该表下的某条数据
                break;
            case TABLE2_DIR:
                //同理
                break;
            case TABLE1_ITEM:
                //同理
                break;
        }
        return null;
    }
    
    @Override
    public Uri insert(Uri uri,ContentValues values){
        /*
        想内容提供器中插入一条数据
        uri:确定插入的表
        values:插入的数据
        
        添加成功后会返回表示该条新数据的uri
        */
        return null;
    }
    
    @Override
    public int update(Uri uri,ContentValues values,String selection,String[] selectionArgs){
        /*
        更新数据时调用该方法
        uri:同理
        values:新的数据
        selection、selectionArgs:更新的条件
        
        返回更新了的行数
        */
        return 0;
    }
    
    @Override
    public int delete(Uri uri,String selection,String[] selectionArgs){
        /*
        删除数据时调用
        uri:同理
        selection、selectionArgs:同理
        
        返回被删除的行数
        */
        return 0;
    }
    
    @Override
    public String getType(Uri uri){
        /*
        调用该方法,是根据传入的uri返回相应的MIME类型
        MIME字符串主要由3部分组成:
        1.vnd开头
        2.如果URI以路径结尾,则后接android.cursor.dir/,
        若以id结尾,则接android.cursor.item/
        3.最后街上vnd.<authority>.<path>
        如下:
        */
        switch(uriMatcher.match(uri)){
              case TABLE1_DIR:
                //以路径结尾
                return "vnd.android.cursor.dir/vnd.com.example.app.provider.table1";
                break;
            case TABLE1_ITEM:
                //以id结尾
                return "vnd.android.cursor.item/vnd.com.example.app.provider.table1";
                break;
            case TABLE2_DIR:
                //同理
                return "vnd.android.cursor.dir/vnd.com.example.app.provider.table2";
                break;
            case TABLE1_ITEM:
                //同理
                return "vnd.android.cursor.item/vnd.com.example.app.provider.table1";
                break;
        }
        
        return null;
    }
}

完整实现跨程序数据共享

public class MyProvider extends ContentProvider{
    
    public static final int TABLE1_DIR = 0;
    public static final int TABLE1_ITEM = 1;
    public static final int TABLE2_DIR = 2;
    public static final int TABLE1_ITEM = 3;
    
    //实现数据库的帮助类
    private MyDatabaseHelper dbHelper;
    
    private static UriMatcher uriMatcher;
    
    static{
        uriMatcher = new UriMatcher(Uri.Matcher.NO_MATCH);
        //第一个参数为authority(一般为应用包名.provider)
        //第二个参数为path,即查询的表
        //第三个参数为自定义码
        uriMatcher.addUri("com.example.app.provider","table1",TABLE1_DIR);
        uriMatcher.addUri("com.example.app.provider","table1/#",TABLE1_ITEM);
        uriMatcher.addUri("com.example.app.provider","table2",TABLE2_DIR);
        uriMatcher.addUri("com.example.app.provider","table2/#",TABLE2_ITEM);
    }
    
    @Override
    public boolean OnCreate(){
        //创建或更新数据库
        dbHelper = new MyDatabaseHelper(context,"dbName.db",null,1);
        return false;//返回true代表初始化成功,false则为失败
    }
    
    @Override
    public Cursor query(Uri uri,String[] projection,String selection,
                        String[] selectionArgs,String sortOrder){
        //查询数据库
        SQLiteDatabase db = dbHelper.getReadableDatabase();
        Cursor cursor = null;
        switch(uriMatcher.match(uri)){
            case TABLE1_DIR:
                curos = db.query("tableName",projection,selection,selectionArgs,
                                null,null,sortOrder);
                //查询该表的全部数据
                break;
            case TABLE1_ITEM:
                //获取查询的id值
                String id = uri.getPathSegments().get(1);
                curos = db.query("tableName",projection,"id = ?",new String[]{id},
                                null,null,sortOrder);
                //查询该表下的某条数据
                break;
            case TABLE2_DIR:
                //类上
                break;
            case TABLE1_ITEM:
                //类上
                break;
        }
        return cursor;
    }
    
    //插入操作与查询操作类似
    @Override
    public Uri insert(Uri uri,ContentValues values){
        /*
        想内容提供器中插入一条数据
        uri:确定插入的表
        values:插入的数据
        
        添加成功后会返回表示该条新数据的uri
        */
        return null;
    }
    //更新操作与查询操作类似
    @Override
    public int update(Uri uri,ContentValues values,String selection,String[] selectionArgs){
        /*
        更新数据时调用该方法
        uri:同理
        values:新的数据
        selection、selectionArgs:更新的条件
        
        返回更新了的行数
        */
        return 0;
    }
    //与查询操作类似
    @Override
    public int delete(Uri uri,String selection,String[] selectionArgs){
        /*
        删除数据时调用
        uri:同理
        selection、selectionArgs:同理
        
        返回被删除的行数
        */
        return 0;
    }
    
    @Override
    public String getType(Uri uri){
        /*
        调用该方法,是根据传入的uri返回相应的MIME类型
        MIME字符串主要由3部分组成:
        1.vnd开头
        2.如果URI以路径结尾,则后接android.cursor.dir/,
        若以id结尾,则接android.cursor.item/
        3.最后街上vnd.<authority>.<path>
        如下:
        */
        switch(uriMatcher.match(uri)){
              case TABLE1_DIR:
                //以路径结尾
                return "vnd.android.cursor.dir/vnd.com.example.app.provider.table1";
                break;
            case TABLE1_ITEM:
                //以id结尾
                return "vnd.android.cursor.item/vnd.com.example.app.provider.table1";
                break;
            case TABLE2_DIR:
                //同理
                return "vnd.android.cursor.dir/vnd.com.example.app.provider.table2";
                break;
            case TABLE1_ITEM:
                //同理
                return "vnd.android.cursor.item/vnd.com.example.app.provider.table1";
                break;
        }
        
        return null;
    }
}

    总体来说,内容提供器的具体操作,与数据库的操作类似,个人认为,其只是封装了数据库的操作,只对传入的路径进行增删改查操作,所以对其他路径的数据不会产生影响,所以安全。

访问其他程序中的数据

     内容提供器的用法一般有两种:
1.使用现有的内容提供器读取和操作相应程序中的数据(如Android系统中的通讯录,短信,媒体库等)
2.创建自己的内容提供器给程序的数据提供外部访问接口(如上)
ContentResolver的基本用法

    使用ContentResolver类,实现访问内容提供器中提供的共享数据,通过Context中的getContentResolver()方法获取其实例。

    ContentResolver提供了对数据的CRUD操作(增删改查)方法,分别是insert()、update()、delete()和query()方法。这些方法中均接受一个内容URI,该URI由authority(一般为应该包名.provider)和path(查询的表名)组成,如:

content://com.eaxmple.app.provider/table

在得到内容URI后,需将其解析为Uri对象,如:

Uri uri = Uri.pare("content://com.eaxmple.app.provider/table");

//然后,利用该uri查询数据
Cursor curso =context.getContentResolver().query(uri,projection,selection,selectionArgs,sortOrder);
//各参数与contentProvider中一样
//update(),insert(),delete()方法与数据库中的类似

然后,通过移动游标的位置遍历Cursor的所有行,取出数据。

if(cursor != null){
    while(cursor.moveToNext()){
        String column1 = cursor.getString(cursor.getColumnIndex("column1"));
        ...
    }
    //使用完关闭释放
    cursor.close();
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值