android四大组件之ContentProvider

目录:

一contentProvider的介绍

二自定义contentProvider的过程

三访问自定义contentProvidre的内容

四例子(获取系统短信和插入系统短信):

五例子(获取系统联系人和插入系统联系人)

六自定义内容观察者

---------------------------------------------------------------------------------------------------------------------------------

一contentProvider的介绍

        <1>contentProvider的介绍

                contentProvider即内容提供者,是android四大组件之一,主要的功能是把本应用的私有数据共享给其他应用访问(主要是数据库信息),也就是让其他应用通过内容提供者访问本应用中的私有数据。

        <2>文件权限

             android文件的权限表示(10个字符):   -rwxrwxxxx

                    第一个字符表示文件的类型:-为文件,d为文件夹

                    第一组rwx:文件拥有者的(owner)权限。(第一个字母代表权限为可读;第二个字母代表权限为可写;第三个字母代表权限为可执行,其中的-代表权限为没有)

                    第二组rwx:同组用户(gruper)的权限(两个应用一般来说都是other用户,除非经过设置才能让两个应用成为同组用户)(微信和qq不是同组用户,是其他用户)

                    第三组rwx;其他用户(other)的权限

           (3)在一个应用下一般来说只有一个数据库,在这个数据库下有很多的表,用来存储信息。当然也可以创建多个数据库。

            <4>contentProvider不是context的子类。

二自定义contentProvider

            <1>自定义contentProvider的步骤:

                    1>自定义一个类继承contentProvider:实现其其中的六个方法oncreate() getType(URI uri),insert(),updata(),delete(),query()

1.oncreate()--这个方法在app启动的时候就会调用,不要执行耗时操作,如果使用  SqliteOpenHelper的话,在这个方法中创建该对象,
				但是不要调用getWriteable()或者getReadable()获取SqliteDatabase对象,获取SqliteDatabase对象的动作
                		应该在具体操作数据的方法(insert(),updata(),delete(),query())中调用
          @return boolean 如果为true,即provider成功加载;否则为false。
2.getType(Uri uri)--返回的是给定的uri上的数据的mimeType类型,如果是数据库文件的话,
                     uri的类型代表的是表的一条数据的时候:例如:table/3的话:vnd.android.cursor.item/name
                    uri的类型代表的是多条数据(比说一个表或者多个表,或者一个表中的多条数据)的时候:vnd.android.cursor.dir/name
                    至于name的命名可以自己随便命名,但是一般是authority+path,比如说:com.example.provider.table1
3.insert(Uri uri,ContentValue values)--第一个参数为authroity+path;
                                       第二个参数:插入数据的对象
                                       return:uri,要插入数据的uri。
4.delete(Uri uri,String selection,String[] selectArgs):第一个参数:authority+path;
                                           第二个参数:条件语句。
                                           第三个参数:条件语句中的values
                                           return: int 需要自己设置,一般来说为删除的行数,
       
5.update(Uri uri,ContentValues values,String selection,String[] selctionArgs)
        第一个参数:authority+path
        第二个参数:要替换的对象values
        第三个参数:条件语句
        第四个参数:条件语句中的values
        return int 需要自己设置,一般来说为替换的总行数  
    
6.query(Uri uri,String[] projection,String selection,String[] selectionArgs,String order):
        第一个参数:authority+path
        第二个参数:要查询的列命的数组
        第三个参数:条件语句
        第四个参数:条件语句的values
        return:Cursor  cursor对象

                    2>在清单文件中注册这个类。使用的是标签<provider>,注意其:

        <provider
            android:name=".contentProviders.MyContentProvider"
//主机号:也就是其他第三方应用访问的根url;
            android:authorities="com.heman.haha"
//是否可以导出,一般为true。
            android:exported="true" />

                    3>一些方法

UriMather
*用于判断一条uri跟指定的多条uri中的哪条匹配。
*匹配原则:
		//指定多条uri
		um.addURI("com.itheima.person", "person", PERSON_CODE);
		um.addURI("com.itheima.person", "company", COMPANY_CODE);
		//#号可以代表任意数字(我们可以在路径之后携带数据,#就是用来携带数字的,可以作为查询条件使用,即将这个
数字作为特定的id,然后进行删除id所在的行,或者插入id所在的行等等)
		//*号代表任意文本(我们可以在路径之后携带数据,*就是用来携带数字的,同样一般也是用来作为条件使用的。)
		um.addURI("com.itheima.person", "person/#", QUERY_ONE_PERSON_CODE);
				此时匹配的还是person表。
                
*通过uri匹配器可以实现操作不同的表:
@Override
		public Uri insert(Uri uri, ContentValues values) {
			if(um.match(uri) == PERSON_CODE){
				db.insert("person", null, values);
			}
			else if(um.match(uri) == COMPANY_CODE){
				db.insert("company", null, values);
			}
			else{
				throw new IllegalArgumentException();
			}
			return uri;
		}
* 如果路径中带有数字,把数字提取出来的api

		int id = (int) ContentUris.parseId(uri);

                      4>例子:

//这是继承contentProvider的类

public class MyContentProvider extends ContentProvider {

    private SQLiteDatabase readableDatabase;
    private UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
    private MySqLiteDatabaseOneOpenhelper sqLiteDatabaseOneOpenhelper;

    {
        /**
         * 第一个参数就是自定义contentprovider在清单文件中authorities的配置
         * 第二个参数path,是每张表的一个唯一的代表,其他应用在访问的时候,传入的url:即Uri.parse("content://authority/path")
         * 第三个代表码,即uriMather.match(uri)的返回值
         * */
        uriMatcher.addURI("com.heman.haha", "person", 1);
        uriMatcher.addURI("com.heman.haha", "teacher", 2);
        uriMatcher.addURI("com.heman.haha", "teacher/#", 3);//#替代所有的数字;*替代所有其他符号
        uriMatcher.addURI("com.heman.haha","*",4); //此时url:Uri.parse("content://com.heman.haha/*)代表的就是person和teacher两张表了
    }

    @Override
    public boolean onCreate() {
        Log.d("qindong","contentProvider的oncreate()方法被调用了");
        //getContext()内容提供者运行在哪个上下文,就用那个上下文。
        sqLiteDatabaseOneOpenhelper = new MySqLiteDatabaseOneOpenhelper(getContext(),3);
        return true;
    }


    @Override
    public String getType(@NonNull Uri uri) {
        String type="no type";
        switch (uriMatcher.match(uri)){
            case 1:
                type="vnd.android.cursor.item/com.heman.haha.person";
                break;
            case 4:
                type="vnd.android.cursor.dir/com.heman.haha.table";
                break;
        }
        return type;
    }


    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
        getReadableDatabase();
        Cursor cursor=null;
        if(uriMatcher.match(uri)==1 ){
            cursor = readableDatabase.query("person", projection, selection, selectionArgs, null, null, sortOrder);
        }else if(uriMatcher.match(uri)==2){
            cursor = readableDatabase.query("teacher", projection, selection, selectionArgs, null, null, sortOrder);
        }else if(uriMatcher.match(uri)==3){
            //获取携带的数据即uri之后的id
            int id= (int) ContentUris.parseId(uri);
            cursor=readableDatabase.query("person",new String[]{"name","phone","money"},"_id=?",new String[]{id+""},null,null,null);
        }
        return cursor;
    }

    @Override
    public Uri insert(Uri uri, ContentValues values) {
        getReadableDatabase();
        if(uriMatcher.match(uri)==1){
            readableDatabase.insert("person", null, values);
            sendSelfNotifyChange(uri);
        }else if(uriMatcher.match(uri)==2){
            readableDatabase.insert("teacher", null, values);
            sendSelfNotifyChange(uri);
        }
        return uri;
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        getReadableDatabase();
        int rows=-1;
        if(uriMatcher.match(uri)==1){
            rows = readableDatabase.delete("person", selection, selectionArgs);
            sendSelfNotifyChange(uri);
        }else if(uriMatcher.match(uri)==2){
            rows = readableDatabase.delete("teacher", selection, selectionArgs);
            sendSelfNotifyChange(uri);
        }
        return rows;
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
        getReadableDatabase();
        int rows=-1;
        if(uriMatcher.match(uri)==1){
            rows= readableDatabase.update("person", values, selection, selectionArgs);
            sendSelfNotifyChange(uri);
        }else if(uriMatcher.match(uri)==2){
            rows = readableDatabase.update("teacher", values, selection, selectionArgs);
            sendSelfNotifyChange(uri);
        }
        return rows;
    }

    //这是当数据库发生改变的时候,发出的通知
    public void sendSelfNotifyChange(Uri uri){
        getContext().getContentResolver().notifyChange(uri,null);
    }

    public void getReadableDatabase(){
        if(null==readableDatabase){
            readableDatabase = sqLiteDatabaseOneOpenhelper.getReadableDatabase();
        }
    }

}
//这是该类在清单文件中的配置
        <provider
            android:name=".contentProviders.MyContentProvider"
            android:authorities="com.heman.haha"
            android:exported="true" />

三访问自定义contentProvidre的内容

            访问自定义contentProvider的内容,此时一般是在别的应用中了,此时我们需要使用contentResolver类了,具体的使用如下:

//1.首先获取到contentResolver对象
contentResolver = getContentResolver();
 //.调用insert方法
contentResolver.insert(Uri uri,ContentVlaues valus);
//调用delete方法
contentResolver.delete(Uri uri,String selection,String[] selectionArgs)
//调用query方法
contentResolver.query(Uri uri,String[] columnNames,String selection,String[] selectinArgs,String order);
//调用update方法
contentResolver.update(Uri uri,ContentValues,String selection,String[] selectionArgs);

            2>注意:

注意在上述方法传入的uri,有一个标签的,即content://,这个比如:
private String mainip="content://com.heman.haha/teacher";
Uri.parse(mainipone)

            3>例子:

private String mainip="content://com.heman.haha/teacher";
    private String mainipone="content://com.heman.haha/teacher/4";
    private String rootPath="content://com.heman.haha";

    private void queryData() {
                //1.获取contentResolver
        ContentResolver   contentResolver = getContentResolver();
        Cursor cursor = contentResolver.query(Uri.parse(mainip), new String[]{"name", "phone", "money"},
                "money>?", new String[]{"1000000"}, null);
        while (cursor.moveToNext()){
            String name = cursor.getString(cursor.getColumnIndex("name"));
            String phone=cursor.getString(cursor.getColumnIndex("phone"));
            int money = cursor.getInt(cursor.getColumnIndex("money"));
            Log.d("qindong",name+"++++++++++++"+phone+"++++++++++++++++++++++"+money);
        }
    }

    private void updateData() {
                //1.获取contentResolver
        ContentResolver   contentResolver = getContentResolver();
        ContentValues contentValue=new ContentValues();
        contentValue.put("name","lisihahahhah");
        contentResolver.update(Uri.parse(mainip),contentValue,"money>?",new String[]{"10000003"});
    }

    private void deleteData() {      
        //1.获取contentResolver
        ContentResolver   contentResolver = getContentResolver();
        contentResolver.delete(Uri.parse(mainip),"money>?",new String[]{"10000005"});
    }

    private void insertData() {
        //1.获取contentResolver
     	ContentResolver   contentResolver = getContentResolver();
        //2.调用insert方法
        ContentValues contentValue=new ContentValues();
        for(int index=0;index<10;index++){
            //首先清空contentValue内容数据
            contentValue.clear();
            contentValue.put("name","张三"+index);
            contentValue.put("phone","1666666666"+index);
            contentValue.put("money","1000000"+index);
            contentResolver.insert(Uri.parse(mainip),contentValue);
        }
    }

		

四例子(获取系统短信和插入系统短信):

                1>简介:

* 只需要关注sms表
* 只需要关注4个字段
	* body:短信内容
	* address:短信的发件人或收件人号码(跟你聊天那哥们的号码)
	* date:短信时间
	* type:1为收到,2为发送
###读取系统短信,首先查询源码获得短信数据库内容提供者的主机名和路径(即sms),然后访问内容提供者(掌握)
##注意系统的短信应用就是一个app应用,此时在我们的app去访问系统的短信,就是两个应用之间的事情,而且系统短信应用提供了contentProvider。

                2>获取系统短信的代码

    public void onquerySms(View view) {
        ContentResolver contentResolver = getContentResolver();
        Cursor cursor = contentResolver.query(Uri.parse("content://sms"), new String[]{"body", "address", "type", "date"}, null, null, null);
        while (cursor.moveToNext()) {
            String body = cursor.getString(cursor.getColumnIndex("body"));
            String address = cursor.getString(cursor.getColumnIndex("address"));
            String type = cursor.getString(cursor.getColumnIndex("type"));
            String date = cursor.getString(cursor.getColumnIndex("date"));
            Log.d("qindong", "这是短信:" + body + "=============" + address + "============" + type + "===========" + date + "==================");
        }
        cursor.close();
    }
   注意:要添加权限:
    <uses-permission android:name="android.permission.READ_SMS"/>

                3>插入系统短信的代码 

   android 4.4以上,系统不允许非短信默认app去插入短信到系统短信库中,所以以下代码在android 4.4以上的结果就是代码执行,但是没有任何效果;如果想要这段代码起作用,必须要将该app设置为默认短信app
    public void insertSms(View view) {
        ContentResolver contentResolver = getContentResolver();
        ContentValues contentValue = new ContentValues();
        contentValue.put("body", "我现在有事,一会给你打电话");
        contentValue.put("address", "15036195507");
        contentValue.put("type", "2");
        contentValue.put("date", System.currentTimeMillis());
        contentResolver.insert(Uri.parse("content://sms"), contentValue);
    }
   注意:要添加权限:
    <uses-permission android:name="android.permission.WRITE_SMS"/>
    <uses-permission android:name="android.permission.READ_SMS"/>

五例子:(获取系统联系人和插入系统联系人)

                1>简介:

* raw_contacts表:
	* contact_id:联系人id
* data表:保存联系人的所有信息,一个信息占一行
	* data1:联系人的每一条具体信息的内容
    						比如说:联系人名字:
                            	列明有很多比如说这三列data1,mimetype_id,raw_contact_id
                                		每列的信息分别是 秦东,2,1
    					这就是所谓的一个信息占一行。
	* raw_contact_id:联系人id,描述该行信息属于哪个联系人
	* mimetype_id:数据的mimetype类型,标识数据属于什么类型。
    *mimetype,数据的mimety类型。
* mimetypes表:通过mimetype_id到该表查看具体类型
###系统联系人同样是一个应用,我们的app是另一个应用,此时我们的app就是在访问别的应用的私有数据,并且系统联系人应用提供了contentProvider。

                1>获取系统联系人:

    /**
     * @funtion 读取系统的联系人资料
     */
    public void querycontact(View view) {
        ContentResolver contentResolver = getContentResolver();
        //1.查询raw_contacts表中的contact_id值,,这个就是每个联系人的id值   其主机号为:com.android.contacts
       
        Cursor cursor = contentResolver.query(Uri.parse("content://com.android.contacts/raw_contacts"), new String[]{"contact_id"}, null, null, null);
        while (cursor.moveToNext()) {
            String contact_id = cursor.getString(cursor.getColumnIndex("contact_id"));
            //当用户将联系人删除的时候,此时系统会将这个联系人的contact_id设置为null,所以此时应该将这种状况排除。
            if (null == contact_id) {
                continue;
            }
            Log.d("qindong", "hahah:" + contact_id);
            //2.查询data表中,根据contact_id,查询data1(名字和号码,email),mimetype(名字和号码,还有email)
            Cursor cursorData = contentResolver.query(Uri.parse("content://com.android.contacts/data"), new String[]{"data1", "mimetype"},
                    "raw_contact_id = ?", new String[]{contact_id}, null);
            Contact contact = new Contact();
            while (cursorData.moveToNext()) {
                String mimetype = cursorData.getString(cursorData.getColumnIndex("mimetype"));
                String data1 = cursorData.getString(cursorData.getColumnIndex("data1"));
                //通过mimetype类型判断是什么那个值
                if ("vnd.android.cursor.item/name".equals(mimetype)) {
                    contact.setName(data1);
                } else if ("vnd.android.cursor.item/email_v2".equals(mimetype)) {
                    contact.setEmail(data1);
                } else if ("vnd.android.cursor.item/phone_v2".equals(mimetype)) {
                    contact.setPhone(data1);
                }
            }
        }
    }
注意:添加权限
    <uses-permission android:name="android.permission.READ_CONTACTS"/>

                1>插入系统联系人:

 /**
     * @funtion 往系统的联系人中插入数据
     */
    public void insertcontact(View view) {
        int contactId = 0;
        //首先查询raw_contact_id表中的contact_id的最大值
        ContentResolver contentResolver = getContentResolver();
         //这次使用_id而不是用contact_id值,是因为当用户将一个联系人删除的时候,此时contact_id的为null,所以我们如果获取这个字段,那么有可能就会获取到null,但是使用
        //_id字段则不会,_id字段是该表的主键,从1开始
        Cursor query = contentResolver.query(Uri.parse(rawcontactsPath), new String[]{"_id"}, null, null, null);
        //这是获取该游标中最后一个值,注意这里用的是if字段,不是while字段,query.moveToLast()为ture的时候,表示此时获取到的最后一个,如果时while,就会无限循环。
        if (query.moveToLast()) {
            contactId = query.getInt(0);
            contactId++;
            Log.d("qindong", contactId + "");
        }
        ContentValues contentValue = new ContentValues();
        contentValue.put("contact_id", contactId);
        contentResolver.insert(Uri.parse(rawcontactsPath), contentValue);

        ContentValues contentValues = new ContentValues();
        contentValues.put("data1", "张三");
        contentValues.put("mimetype", "vnd.android.cursor.item/name");
        contentValues.put("raw_contact_id", contactId);
        contentResolver.insert(Uri.parse(dataPath), contentValues);

        contentValues.clear();
        contentValues.put("data1", "15035281908");
        contentValues.put("mimetype", "vnd.android.cursor.item/phone_v2");
        contentValues.put("raw_contact_id", contactId);
        contentResolver.insert(Uri.parse(dataPath), contentValues);

    }
注意:添加权限
    <uses-permission android:name="android.permission.WRITE_CONTACTS"/>
    <uses-permission android:name="android.permission.READ_CONTACTS"/>

六、自定义内容观察者:

              当内容提供者操作的数据发生改变的时候,此时内容提供者会发出一个通知,而内容观察者就会收到这个通知,然后根据自己的业务需求做一些操作。但是想要内容提供者操作的数据发生改变,内容提供者发出通知,这个是要对内容提供者进行修改的。

            1>内容提供者发出通知:

            ContentResolver contentResolver = getContext().getContentResolver();
//第一个参数是uri,第二个参数是contentObserve对象(可指定对象,若为null,即不指定)
            contentResolver.notifyChange(uri,null);

            2>内容观察者接受通知:

  ContentResolver contentResolver = getContentResolver();
				//第二个参数 boolean  如果为true,那么以这个第一个参数中的uri为开头的所有uri,发生改变的时候,此时你都可以收到通知。	
				//					  如果为false,仅仅是第一个参数中的uri,即使是以第一个uri开头的uri,你也收不到,只有和你的uri一模一样时, 你才能收到通知。  我们一般设置为true.


        contentResolver.registerContentObserver(Uri.parse("content://com.heman.haha/teacher"),true,new ContentObserver(new Handler()) {
            /**
             * 这两个方法任何一个都行,如果有onChange(boolean selfChange, Uri uri)则方法public void onChange(boolean selfChange) 
             * 不会执行,如果只有public void onChange(boolean selfChange),则该方法执行。
             * */
            @Override
            public void onChange(boolean selfChange) {
            }
            //第二个参数uri,即表示那个uri发生了变化,因为我们registerContentObserver()第二个参数设置为true,所以说具体的uri有可能是和我们的传入的第一个参数是不同的
            //这个地方的uri是一个具体的uri。
            @Override
            public void onChange(boolean selfChange, Uri uri) {
            }
        });

             3>完整的例子:

//这是应用A的contentProvider
public class MyContentProvider extends ContentProvider {

    private SQLiteDatabase readableDatabase;
    private UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
    private MySqLiteDatabaseOneOpenhelper sqLiteDatabaseOneOpenhelper;

    {
        /**
         * 第一个参数就是自定义contentprovider在清单文件中authorities的配置
         * 第二个参数path,是每张表的一个唯一的代表,其他应用在访问的时候,传入的url:即Uri.parse("content://authority/path")
         * 第三个代表码,即uriMather.match(uri)的返回值
         * */
        uriMatcher.addURI("com.heman.haha", "person", 1);
        uriMatcher.addURI("com.heman.haha", "teacher", 2);
        uriMatcher.addURI("com.heman.haha", "teacher/#", 3);//#替代所有的数字;*替代所有其他符号
        uriMatcher.addURI("com.heman.haha","*",4); //此时url:Uri.parse("content://com.heman.haha/*)代表的就是person和teacher两张表了。
    }

    @Override
    public boolean onCreate() {
        Log.d("qindong","contentProvider的oncreate()方法被调用了");
        //getContext()内容提供者运行在哪个上下文,就用那个上下文。
        sqLiteDatabaseOneOpenhelper = new MySqLiteDatabaseOneOpenhelper(getContext(),3);
        return true;
    }


    @Override
    public String getType(@NonNull Uri uri) {
        String type="no type";
        switch (uriMatcher.match(uri)){
            case 1:
                type="vnd.android.cursor.item/com.heman.haha.person";
                break;
            case 4:
                type="vnd.android.cursor.dir/com.heman.haha.table";
                break;
        }
        return type;
    }


    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
        getReadableDatabase();
        Cursor cursor=null;
        if(uriMatcher.match(uri)==1 ){
            cursor = readableDatabase.query("person", projection, selection, selectionArgs, null, null, sortOrder);
        }else if(uriMatcher.match(uri)==2){
            cursor = readableDatabase.query("teacher", projection, selection, selectionArgs, null, null, sortOrder);
        }else if(uriMatcher.match(uri)==3){
            //获取携带的数据即uri之后的id
            int id= (int) ContentUris.parseId(uri);
            cursor=readableDatabase.query("person",new String[]{"name","phone","money"},"_id=?",new String[]{id+""},null,null,null);
        }
        return cursor;
    }

    @Override
    public Uri insert(Uri uri, ContentValues values) {
        getReadableDatabase();
        if(uriMatcher.match(uri)==1){
            readableDatabase.insert("person", null, values);
            sendSelfNotifyChange(uri);
        }else if(uriMatcher.match(uri)==2){
            readableDatabase.insert("teacher", null, values);
            sendSelfNotifyChange(uri);
        }
        return uri;
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        getReadableDatabase();
        int rows=-1;
        if(uriMatcher.match(uri)==1){
            rows = readableDatabase.delete("person", selection, selectionArgs);
            sendSelfNotifyChange(uri);
        }else if(uriMatcher.match(uri)==2){
            rows = readableDatabase.delete("teacher", selection, selectionArgs);
            sendSelfNotifyChange(uri);
        }
        return rows;
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
        getReadableDatabase();
        int rows=-1;
        if(uriMatcher.match(uri)==1){
            rows= readableDatabase.update("person", values, selection, selectionArgs);
            sendSelfNotifyChange(uri);
        }else if(uriMatcher.match(uri)==2){
            rows = readableDatabase.update("teacher", values, selection, selectionArgs);
            sendSelfNotifyChange(uri);
        }
        return rows;
    }

    //这是当数据库发生改变的时候,发出的通知
    public void sendSelfNotifyChange(Uri uri){
        getContext().getContentResolver().notifyChange(uri,null);
    }

    public void getReadableDatabase(){
        if(null==readableDatabase){
            readableDatabase = sqLiteDatabaseOneOpenhelper.getReadableDatabase();
        }
    }

}
//这是应用B中的注册的内容观察者
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        initEvent();
        getContentProviderNotify();
    }

    private void getContentProviderNotify() {
        ContentResolver contentResolver = getContentResolver();
        contentResolver.registerContentObserver(Uri.parse("content://com.heman.haha/teacher"),true,new ContentObserver(new Handler()) {
            /**
             * 这两个方法任何一个都行,如果有onChange(boolean selfChange, Uri uri)则方法public void onChange(boolean selfChange)
             * 不会执行,如果只有public void onChange(boolean selfChange),则该方法执行。
             * */
            @Override
            public void onChange(boolean selfChange) {
            }
            //返回的uri就是我们在使用contentResolver操作数据库时,传入的uri,可用于判断是哪个表发生了变化。
            @Override
            public void onChange(boolean selfChange, Uri uri) {
            }
        });
    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值