现在的位置: 首页 > 移动开发 > 正文

Android学习笔记—监听ContentProvider(内容共享者)中数据的变化

2019年09月19日 移动开发 ⁄ 共 7453字 ⁄ 字号 评论关闭

2013-03-16
监听ContentProvider中数据的变化
------------------------------------------
1.如果ContentProvider的访问者需要得知ContentProvider中的数据发生了变化,可以在

ContentProvider 发生数据变化时调用getContentResolver().notifyChange(uri, null)来

通知注册在此URI上的访问者,例子如下:
public class PersonContentProvider extends ContentProvider {
public Uri insert(Uri uri, ContentValues values) {
db.insert("person", "personid", values);
getContext().getContentResolver().notifyChange(uri, null);
}
}
如果ContentProvider的访问者需要得到数据变化通知,必须使用ContentObserver对数据(

数据采用uri描述)进行监听,当监听到数据变化通知时,系统就会调用ContentObserver的

onChange()方法:
getContentResolver().registerContentObserver(Uri.parse

("content://cn.itcast.providers.personprovider/person"),
        true, new PersonObserver(new Handler()));
public class PersonObserver extends ContentObserver{
public PersonObserver(Handler handler) {
super(handler);
  }
public void onChange(boolean selfChange) {
   //此处可以进行相应的业务处理
}
}
--------------------------------------------------------
2.应用场景,有两个应用,
  A应用       B应用
      ContentProvider
  A,B两个应用都需要访问ContentProvider,A应用首先会往ContentProvider
  中添加一条数据,B应用需要立刻得到A应用添加进去的这条数据,这时候
  需要用到:监听ContentProvider中数据的变化,当A应用往ContentProvider中添加
  数据的时候,ContentProvider会发出数据变化通知,这时候,B应用通过监听就可以得知这个
  变化通知;
---------------------------------------------
3.使用ContentResolver对ContentProvider中的数据进行添加、删除、修改和查询操作:
ContentResolver resolver =  getContentResolver();
Uri uri = Uri.parse("content://cn.itcast.provider.personprovider/person");
//添加一条记录
ContentValues values = new ContentValues();
values.put("name", "itcast");
values.put("age", 25);
resolver.insert(uri, values);
//获取person表中所有记录
Cursor cursor = resolver.query(uri, null, null, null, "personid desc");
while(cursor.moveToNext()){
Log.i("ContentTest", "personid="+ cursor.getInt(0)+ ",name="+ 

cursor.getString(1));
}
//把id为1的记录的name字段值更改新为liming
ContentValues updateValues = new ContentValues();
updateValues.put("name", "liming");
Uri updateIdUri = ContentUris.withAppendedId(uri, 2);
resolver.update(updateIdUri, updateValues, null, null);
//删除id为2的记录
Uri deleteIdUri = ContentUris.withAppendedId(uri, 2);
resolver.delete(deleteIdUri, null, null);
-----------------------------------------------------------------
4.下面是详细代码:
   a.首先:在ContentProviderDBSQLIte项目中的PersonProvider.java类中修改,insert方法
     /ContentProviderDBSQLIte/src/com/credream/db/PersonProvider.java
-------------------------------
//可以供外部的应用查询,往内容提供者中插入数据
//ContentValues用于存放各个字段的值
@Override
public Uri insert(Uri uri, ContentValues values)
{
//往数据库中插入数据
SQLiteDatabase db=dbOpenHelter.getWritableDatabase();
switch(MATCHER.match(uri)){
case 1:
long rowid=db.insert("person", "name", values);//行号,如

果主键是整形的,并且是增长的话,那么这个是值就是主键值;
//第二个参数,外面values如果传一个null,或者是空集合,这时候

第二个参数采用的上,给一个默认值
//返回的事uri

//content://com.credream.providers.personprovider/person/10
//第一种获得这一行的uri的方法
//Uri insertUri=Uri.parse

("content://com.credream.providers.personprovider/person/"+rowid);
//content://com.credream.providers.personprovider/person/
//第二种获得这一行的uri的方法
Uri insertUri=ContentUris.withAppendedId(uri, rowid);
 this.getContext().getContentResolver().notifyChange(uri, 

null);//发出数据变化通知,B应用可以得到这个通知
          //notifyChange(uri, observer)//第一个参数,uri是要发生数据变化的来源uri,
 //第二个参数,数据变化的监听者,可以不设置,也即是设为null,如果给

定了这个监听者,不管外面有多少个应用要设置监听,进行监听数据变化
 //这个getContentResolver()监听对象,必然会得到数据的变化通知

return insertUri;
//break;//ResNo不是行号,
default:
throw new IllegalArgumentException("this is Unknow 

Uri"+uri);
}
}
-------------------------------------------------------
b.创建Bapp项目,该项目是拷贝于OherFile项目,然后修改该项目的OherFileActivity.java类
----------------------------------------------------------------
/Bapp/src/com/credream/otherfile/OherFileActivity.java
package com.credream.otherfile;

import android.app.Activity;

import android.content.ContentResolver;

import android.content.Context;

import android.database.ContentObserver;

import android.database.Cursor;

import android.net.Uri;

import android.os.Bundle;

import android.os.Handler;

import android.util.Log;

public class OherFileActivity extends Activity {
  
 static final String TAG="OherFileActivity";

/** Called when the activity is first created. */
    @Override
   
 public void onCreate(Bundle savedInstanceState) {
        super.onCreate

(savedInstanceState);
       
 setContentView(R.layout.main);

 //注册数据变化监听器
        
Uri uri=Uri.parse("content://com.credream.providers.personprovider/person");
      

this.getContentResolver().registerContentObserver(uri, true, new 

PersonContentObserver(new Handler()));
       
 //注意:当registerContentObserver(uri, true, new PersonContentObserver(new 

//Handler()));
     
   //当uri代表的数据源发生改变时候,会自动调用public void onChange(boolean 

//selfChange)这个方法
 

        /*  notifyForDescendents  If true changes to 

URIs beginning with uri will also cause notifications to be sent. If false only 

changes to the exact URI specified by uri will cause notifications to be sent. If 

true, than any URI values at or below the specified URI will also trigger a 

match. 
        observer  The object that receives callbacks when changes occur. 
*/
   
 }
  
  private class PersonContentObserver extends ContentObserver{


public PersonContentObserver(Handler handler)
{

super(handler);

 
}
//这个boolean selfChange,是自身(本应用)修改变数据发生的

改变吗,是就为true,否则为false

@Override
public void onChange(boolean selfChange)
{

//select * from person order by personid desc limit 1得到最近添

加的那条数据
Uri uri=Uri.parse

("content://com.credream.providers.personprovider/person");

Cursor cursor= getContentResolver().query(uri, null, null, null, "personid desc 

limit 1");

/*这句SQL的结构是:select projection from table where ( selection ) order by 

order; 

 projection是我们要查询的列;
 
table是根据Uri确定的数据库表;
selection使我们自己的查询条件;

order是我们想要的排序方式。
*/

if(cursor.moveToFirst()){

String name=cursor.getString(cursor.getColumnIndex("name"));

Log.i(TAG, name);
}

super.onChange(selfChange);
}

 
   
    }
    
}
-----------------------------------------------------------------
c.创建Aapp项目
package com.credream.ContentProviderGetInfo;

import android.app.Activity;

import android.content.ContentResolver;

import android.content.ContentValues;

import android.net.Uri;

import android.os.Bundle;

import android.view.View;

public class AappActivity extends Activity {
  
  /** Called when the activity is first created. */
  
  @Override
   
 public void onCreate(Bundle savedInstanceState) {
     
   super.onCreate(savedInstanceState);
       
 setContentView(R.layout.main);
    }
   
 //要求的签名一定要是这种格式,也就是这个方法一定要写成这种格式
  
  public void  insert(View v){
   
Uri uri=Uri.parse("content://com.credream.providers.personprovider/person/");
   

ContentResolver resolver=this.getContentResolver();
   
  ContentValues values=new ContentValues();
    
values.put("name", "A-APP");
   
values.put("phone", "188868451");
   
values.put("amount", "8000000");
   
resolver.insert(uri, values);//在insert内部会调用内容提供者的insert方法
   

//当点击A应用的按钮的时候就会插入数据,执行这个方法

    }
}
------------------------------------------------------------
/Aapp/res/layout/main.xml
<?xml version="1.0" encoding="utf-8"?>
<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="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/button"
        android:onClick="insert" /><!--//指定按钮被点击之后要执行的方法

--></LinearLayout>
---------------------------------
/Aapp/res/values/strings.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="hello">Hello World, AappActivity!</string>
    <string name="app_name">Aapp应用</string>
 <string name="button">网内容提供者提供数据</string>
</resources>
---------------------------------------------------------
d.然后就可以测试了,测试的时候,先启动ContentProviderDBSQLIte项目
  然后启动:Bapp,Bapp项目用来监听ContentProviderDBSQLIte发出的通知
  然后启动:Aapp项目
------------------------------
e.Aapp项目,insert数据的时候,ContentProviderDBSQLIte项目会产生通知,因为Bapp项目
  设置了监听所以,会得到通知,而触发事件得到刚刚添加的数据,并把name打印出来:
  03-16 13:20:23.640: I/OherFileActivity(308): A-APP

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

抱歉!评论已关闭.