1,介绍:
【1】ContentObserver——内容观察者,目的是观察(捕捉)特定Uri引起的数据库的变化,做一些相应的处理,它类似于数据库技术中的触发器(Trigger),当ContentObserver所观察的Uri发生变化时,便会触发它。触发器分为表触发器、行触发器,
熟悉Content Provider(内容提供者)的应该知道,我们可以通过UriMatcher类注册不同类型的Uri,我们可以通过这些不同的
Uri来查询不同的结果。根据Uri返回的结果。
【2】ContentObserver不是四大组件不需要在androidmanifest 注册。
1,应用1 (内容提供者)
【1】创建数据库
public class MyOpenHelper extends SQLiteOpenHelper {
/**
* @param context
* name :数据库名字
* factory: 游标工厂
* version: 数据库的版本
*/
public MyOpenHelper(Context context) {
super(context, "account.db", null, 1);
}
//Called when the database is created for the first time. 当数据库第一次创建的时候调用 那么这个方法适合做表结构的初始化
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("create table info (_id integer primary key autoincrement,name varchar(20),phone varchar(20),money varchar(20))");
db.execSQL("insert into info ('name','phone','money') values ('张三','138888','2000')");
db.execSQL("insert into info ('name','phone','money') values ('李四','139999','5000')");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
【2】AccountProvider 继承ContentProvider 重写方法,暴露QIUD方法。
getContext().getContentResolver().notifyChange(uri, null);方法通知内容观察者
public class AccountProvider extends ContentProvider {
// [1]定义一个urimatcher路径匹配器
private static final UriMatcher sURIMatcher = new UriMatcher(
UriMatcher.NO_MATCH);
private static final int QUERYSUCESS = 0;
private static final int INSERTSUCESS = 1;
private static final int UPDATESUCESS = 2;
private static final int DELETESUCESS = 3;
private MyOpenHelper myOpenHelper;
// [2]在静态代码块中添加路径
static {
/**
* authority:要和你在清单文件里面声明authority一样
*
* URL:统一资源定位符 https://www.baidu.com/tieba Uri:统一资源标识符
* com.itheima.db/query uri就是自己定义的一个路径 代表一个含义
*
*/
sURIMatcher.addURI("com.xiaoshuai.db", "query", QUERYSUCESS);
sURIMatcher.addURI("com.xiaoshuai.db", "insert", INSERTSUCESS);
sURIMatcher.addURI("com.xiaoshuai.db", "update", UPDATESUCESS);
sURIMatcher.addURI("com.xiaoshuai.db", "delete", DELETESUCESS);
}
@Override
public boolean onCreate() {
myOpenHelper = new MyOpenHelper(getContext());
return false;
}
// 把这个方法对外暴露出去
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
// [1]获取一个匹配码
int code = sURIMatcher.match(uri);
if (code == QUERYSUCESS) {
// 说明路径匹配成功 把这个方法实现 实际上就是在这个方法对数据库进行查询的操作
SQLiteDatabase db = myOpenHelper.getReadableDatabase();
Cursor cursor = db.query("info", projection, selection,selectionArgs, null, null, sortOrder);
//[2]当对数据库进行查询操作后 自己主动的发送一条消息
getContext().getContentResolver().notifyChange(uri, null);
return cursor;
} else {
// 代表路径匹配失败
return null;
// throw new IllegalArgumentException("哥们路径不正确 ,请检查路径");
}
}
@Override
public String getType(Uri uri) {
return null;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
int code = sURIMatcher.match(uri);
if (code == INSERTSUCESS) {
// 代表路径匹配成功 把insert方法实现
SQLiteDatabase db = myOpenHelper.getReadableDatabase();
// 代表新插入行的id
long insert = db.insert("info", null, values);
Uri uri2 = Uri.parse("com.itheima.insert/" + insert);
if (insert > 0) {
//[2]当对数据库进行查询操作后 自己主动的发送一条消息
getContext().getContentResolver().notifyChange(uri, null);
}
return uri2;
} else {
return null;
}
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
int code = sURIMatcher.match(uri);
if (code == DELETESUCESS) {
// 代表路径匹配成功 把insert方法实现
SQLiteDatabase db = myOpenHelper.getReadableDatabase();
// 代表删除的行数
int delete = db.delete("info", selection, selectionArgs);
if (delete > 0) {
//[2]当对数据库进行查询操作后 自己主动的发送一条消息
getContext().getContentResolver().notifyChange(uri, null);
}
return delete;
} else {
return 0;
}
}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
int code = sURIMatcher.match(uri);
if (code == UPDATESUCESS) {
// 代表路径匹配成功 把insert方法实现
SQLiteDatabase db = myOpenHelper.getReadableDatabase();
// 代表更新的行数
int update = db.update("info", values, selection, selectionArgs);
if (update > 0) {
//[2]当对数据库进行查询操作后 自己主动的发送一条消息
getContext().getContentResolver().notifyChange(uri, null);
}
return update;
} else {
return 0;
}
}
}
【3】Android Manifest中声明provider
2,应用2 (内容解析者)
【1】获取内容解析者,通过URI 调用QIUD 方法 进行操作 ContentResolver
public void click(View v) {
Log.e("Main", "我被点击了。不是我的错");
ContentResolver resolver = getContentResolver();
Uri uri = Uri.parse("content://com.xiaoshuai.db/query");
Cursor cursor = resolver.query(uri, null, null, null, null);
if (cursor != null && cursor.getCount() > 0) {
// ★★★ 想取出数据必须移动游标
while (cursor.moveToNext()) {
String name = cursor.getString(1);
String money = cursor.getString(3);
Log.e("Main", "第二个应用~~name:" + name + "----" + money);
}
cursor.close();
}
}
//add
public void click1(View v) {
// [1]由于第一个应用的数据库系统已经通过内容提供者暴露出来 所以可以直接通过内容解析者操作数据库
Uri uri = Uri.parse("content://com.xiaoshuai.db/insert");
// [2]创建contentValues
ContentValues values = new ContentValues();
// 参数1 是表的列名:
values.put("name", "王五");
values.put("money", "100");
// [3]往数据库里面插入了一条数据
Uri insert = getContentResolver().insert(uri, values);
Log.e("Main","insert" +insert);
}
public void click2(View v) {
Uri uri = Uri.parse("content://com.xiaoshuai.db/delete");
int delete = getContentResolver().delete(uri, "name=?",
new String[] { "王五" });
Toast.makeText(getApplicationContext(), "删除了" + delete + "行", Toast.LENGTH_LONG).show();
}
public void click3(View v) {
Uri uri = Uri.parse("content://com.xiaoshuai.db/update");
ContentValues values = new ContentValues();
values.put("money", "10000");
int update = getContentResolver().update(uri, values, "name=?",
new String[] { "王五" });
Toast.makeText(getApplicationContext(), "修改了了" + update + "行", Toast.LENGTH_SHORT)
.show();
}
}
3,应用3 (内容观察者)
【1】 getContentResolver().registerContentObserver(uri, true, new MyContentObserver(new Handler())); 注册内容观察者进行监听。
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//[1]注册内容观察者 还是使用内容解析者去注册
Uri uri = Uri.parse("content://com.xiaoshuai.db/");
//[2]注册内容观察者 参数二:如果是false 那么第一个参数的uri必须是一个精确的uri true:可以不用是一个精确的uri
getContentResolver().registerContentObserver(uri, true, new MyContentObserver(new Handler()));
}
//定义内容观察者
private class MyContentObserver extends ContentObserver{
public MyContentObserver(Handler handler) {
super(handler);
}
//当我们观察的内容发生变化 这个方法就执行
@Override
public void onChange(boolean selfChange) {
System.out.println("哈哈 数据库被人操作了");
super.onChange(selfChange);
}
}
}