四大应用组件之ContentProvider

一、理论概述

1、为什么要有ContentProvider? 

功能需求: 一个应用需要访问另一个应用的数据库表数据 

实际情况: 一个应用的数据库文件是应用私有的, 其它应用不能直接访问。

2、ContentProvider是什么? 

ContentProvider是四大应用组件之一 

当前应用使用ContentProvider将数据库表数据操作暴露给其它应用访问 

其它应用需要使用ContentResolver来调用ContentProvider的方法 

它们之间的调用是通过Uri来进行交流的

3、相关API (1) 

ContentProvider  : 内容提供者类 

//provider对象创建后调用(应用安装成功或手机启动完成)

public abstract boolean onCreate();

//查询表数据 

Cursor query(Uri uri, String[] projection,String selection, String[] selectionArgs)

//插入表数据 

Uri insert(Uri uri, ContentValues values);

//删除表数据 

int delete(Uri uri, String selection, String[] selectionArgs)

//更新表数据 

update(Uri uri, ContentValues values, String selection,String[] selectionArgs); 

 

4、相关API (2) 

ContentResolver:  内容提供者的解析类 

//得到它的对象 

context.getContentResolver() 

//调用provider进行数据库CRUD操作 

Insert()、delete()、update()、query()

//注册uri的监听 

registerContentObserver(Uri uri, boolean notify,ContentObserver observer)

//解注册uri的监听 

unregisterContentObserver(ContentObserver observer)

//通知监听器 

notifyChange(Uri uri, ContentObserver observer)

 

5、相关API (3) 

Uri: 包含请求地址数据的类 

//得到其对象 

Uri static parse(String uriString)

A : 是一个前缀,表示是由ContentProvider提供,固定不变

B : authority, 标识是哪个Provider,不同的Provider此部分必须不同。

C : 对应于哪张表 student 

D : id值, 对应表中的哪条记录

 

6、相关API (4) 

UriMatcher : 用于匹配Uri的容器 

//添加一个合法的URI 

void addURI(String authority, String path, int code) 

//匹配指定的uri, 返回匹配码 

int match(Uri uri) 

 

ContentUris : 解析uri的工具类 

//解析uri, 得到其中的id 

long parseId(Uri contentUri) 

//添加id到指定的uri中 

Uri withAppendedId(Uri contentUri, long id) 

 

二、ContentProvider开发 

1、 基本步骤

(1)编写ContentProvider子类 

class StudentContentProvider extends ContentProvider {

//实现inert、delete、update和query等方法 

}

(2)在manifest.xml中注册 

<provider

         android:name=".StudentContentProvider"

         android:authorities="com.atguigu.provider.studentprovider" 

android:exported="true"/> 

 

2、基本步骤

(1)得到其对象 

context.getContentResolver()

(2)使用其对象 

inert()、delete()、update()和query()

系统自动找到匹配的ContentProvider对象来操作数据 

registerContentObserver(Uri uri, boolean notify,ContentObserver observer)

注册uri的监听 

unregisterContentObserver(ContentObserver observer)

解注册uri的监听 

notifyChange(Uri uri, ContentObserver observer)

通知监听器 

 

实现原理:被调用端继承ContentProvider实现数据库的增删改查,然后再AndroidManifest.xml注册peovider。调用端用ContentResolver通过Uri调用被调用端的ContentProvider。

 

三、实例 被调用端   ContentProvider 

在这个文件中实现数据库的增删改查

/**
 * person数据表的ContentProvoder
 */

public class PersonProvider extends ContentProvider {

    //用来存放所有合法的Uri的容器
    private static UriMatcher matcher=new UriMatcher(UriMatcher.NO_MATCH);
    //保存一些合法的uri
    // content://com.example.contentprovider.PersonProvider/person 不根据id操作
    // content://com.example.contentprovider.PersonProvider/person/3 根据id操作
    static{
        matcher.addURI("com.example.contentprovider.PersonProvider","/person",1);
        matcher.addURI("com.example.contentprovider.PersonProvider","/person/#",2); //#匹配任意数字
    }

    private DBHelper dbHelper;

    public PersonProvider() {
        Log.e("TAG", "PersonProvider()");
    }

    @Override
    public boolean onCreate() {
        Log.e("TAG", "PersonProvider onCreate()");
        dbHelper=new DBHelper(getContext());
        return false;
    }

    // content://com.example.contentprovider.PersonProvider/person 不根据id查询
    // content://com.example.contentprovider.PersonProvider/person/3 根据id查询
    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
        Log.e("TAG", "PersonProvider query()");
        //得到数据库连接对象
        SQLiteDatabase database=dbHelper.getReadableDatabase();
        //1.匹配uri, 返回code
        int code=matcher.match(uri);
        //如果合法, 进行查询
        if(code==1){//不根据id查询
            Cursor cursor=database.query("person",projection,selection,selectionArgs,null,null,null);
            return cursor;
        }else if(code==2){
            long id= ContentUris.parseId(uri);
            Cursor cursor=database.query("person",projection,"_id=?",new String[]{id+""},null,null,null);
            return cursor;
        }
        return null;
    }

    @Override
    public String getType(@NonNull Uri uri) {
        return null;
    }

    // content://com.example.contentprovider.PersonProvider/person 插入
    // content://com.example.contentprovider.PersonProvider/person/3 根据id插入(没有)
    @Override
    public Uri insert(Uri uri, ContentValues values) {
        Log.e("TAG", "PersonProvider insert()");
        //得到数据库连接对象
        SQLiteDatabase database=dbHelper.getReadableDatabase();
        //1.匹配uri, 返回code
        int code=matcher.match(uri);
        //如果合法, 进行插入
        if(code==1){//不根据id查询
            long id=database.insert("person",null,values);
            uri=ContentUris.withAppendedId(uri,id);
            database.close();
            return uri;
        }else{
            //如果不合法, 抛出异常
            database.close();
            throw new RuntimeException("插入的uri不合法");
        }
    }

    // content://com.example.contentprovider.PersonProvider/person 不根据id删除
    // content://com.example.contentprovider.PersonProvider/person/3 根据id删除
    @Override
    public int delete(Uri uri, String selection,String[] selectionArgs) {
        Log.e("TAG", "PersonProvider delete()");
        //得到数据库连接对象
        SQLiteDatabase database=dbHelper.getReadableDatabase();
        //1.匹配uri, 返回code
        int code=matcher.match(uri);
        int deleteCount=-1;
        //如果合法, 进行删除
        if(code==1){//不根据删除
            deleteCount= database.delete("person",selection,selectionArgs);
        }else if(code==2){//根据id删除
            long id= ContentUris.parseId(uri);
            deleteCount= database.delete("person","_id=?",new String[]{id+""});
        }else{
            database.close();
            //如果不合法, 抛出异常
            throw new RuntimeException("删除的uri不合法");
        }
        database.close();
        return deleteCount;
    }

    // content://com.example.contentprovider.PersonProvider/person 不根据id更新
    // content://com.example.contentprovider.PersonProvider/person/3 根据id更新
    @Override
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
        Log.e("TAG", "PersonProvider update()");
        //得到数据库连接对象
        SQLiteDatabase database=dbHelper.getReadableDatabase();
        //1.匹配uri, 返回code
        int code=matcher.match(uri);
        int updateCount=-1;
        //如果合法, 进行更新
        if(code==1){//不根据删除更新
            updateCount=database.update("person",values,selection,selectionArgs);
        }else if (code==2){
            long id=ContentUris.parseId(uri);
            updateCount=database.update("person",values,"_id="+id,null);
        }else{
            //如果不合法, 抛出异常
            throw new RuntimeException("更新的uri不合法");
        }
        database.close();
        return updateCount;
    }
}

数据库帮助类

/**
 * 数据库帮助类
 */

public class DBHelper extends SQLiteOpenHelper {

    public DBHelper(Context context) {
        super(context, "haitao", null, 1);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        Log.e("TAG", "onCreate()...");
        //建表
        db.execSQL("create table person(_id integer primary key autoincrement, name varchar)");
        //插入初始化数据
        db.execSQL("insert into person (name) values ('Tom')");

    }

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

    }
}

AndroidManifest.xml

 <provider
            android:name=".PersonProvider"
            android:authorities="com.example.contentprovider.PersonProvider"
            android:exported="true">
            <!-- exported : 是否可以让其它应用访问 -->
        </provider>

四、调用端   ContentResolver

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    //通过ContentResolver调用ContentProvider插入一条记录
    public void insert(View v){
        //1. 得到ContentResolver对象
        ContentResolver resolver=getContentResolver();
        //2. 调用其insert
        Uri uri=Uri.parse("content://com.example.contentprovider.PersonProvider/person");
        ContentValues values=new ContentValues();
        values.put("name","haitao");
        uri = resolver.insert(uri,values);
        Toast.makeText(this, uri.toString(),Toast.LENGTH_SHORT).show();
    }

    //通过ContentResolver调用ContentProvider更新一条记录
    public void update(View v){
        //1. 得到ContentResolver对象
        ContentResolver resolver=getContentResolver();
        //2. 调用其update
        Uri uri=Uri.parse("content://com.example.contentprovider.PersonProvider/person/2");//更新person表的id为2的数据
        ContentValues values=new ContentValues();
        values.put("name","jack");
        int updateCount =resolver.update(uri,values,null,null);
        Toast.makeText(this, "updateCount="+updateCount,Toast.LENGTH_SHORT).show();
    }

    //通过ContentResolver调用ContentProvider删除一条记录
    public void delete(View v){
        //1. 得到ContentResolver对象
        ContentResolver resolver=getContentResolver();
        //2. 调用其delete
        Uri uri=Uri.parse("content://com.example.contentprovider.PersonProvider/person/2");//删除person表的id为2的数据
        int deleteCount=resolver.delete(uri,null,null);
        Toast.makeText(this, "deleteCount="+deleteCount, Toast.LENGTH_SHORT).show();
    }

    //通过ContentResolver调用ContentProvider查询所有记录
    public void query(View v){
        //1. 得到ContentResolver对象
        ContentResolver resolver=getContentResolver();
        2. 调用其query, 得到cursor
        Uri uri=Uri.parse("content://com.example.contentprovider.PersonProvider/person/2");//查询person表的id为2的记录
        uri=Uri.parse("content://com.example.contentprovider.PersonProvider/person");//查询所有记录
        Cursor cursor=resolver.query(uri,null,null,null,null);
        while(cursor.moveToNext()){
            int id=cursor.getInt(0);//获取_id的值
            String name=cursor.getString(1);//获取名字
            Toast.makeText(this,id+":"+name,Toast.LENGTH_SHORT).show();
        }
        cursor.close();
    }
}

 

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical" >

        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:onClick="insert"
            android:text="INSERT" />

        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:onClick="delete"
            android:text="DELETE" />

        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:onClick="update"
            android:text="UPDATE" />

        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:onClick="query"
            android:text="QUERY" />

    </LinearLayout>

 

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值