android菜鸟学习笔记22----ContentProvider(二)ContentObserver的简单使用
现在有这样一个应用A通过ContentProvider提供自己的数据给其他应用,应用B通过ContentResolver获取应用A中提供的数据,并将其展示在ListView中,而应用C通过ContentResolver修改应用A中的数据,或者添加新的数据。现在的问题是应用C修改A中数据后,应用B的ListView中显示的还是历史数据……

具体程序如下:
ContentProvider和插入数据的应用分别复用上一篇中的两个应用,然后新建一个应用,用于获取ContentProvider中的数据,并在一个ListView中展示:
布局文件activity _main.xml中添加一个ListView:
<ListView
android:id="@+id/lv"
android:layout_width="match_parent"
android:layout_height="wrap_content"></ListView>
布局文件item_layout.xml用于显示ListView中的条目:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<TextView
android:id="@+id/tv_id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"/>
<TextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"/>
<TextView
android:id="@+id/tv_gender"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"/>
<TextView
android:id="@+id/tv_age"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"/>
</LinearLayout>
MainActivity添加获取数据并显示到ListView的代码:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
uri = Uri.parse("content://cn.csc.content_provider/t_student");
Cursor cursor = getContentResolver().query(uri, new String[]{"id as _id","name","gender","age"}, null, null, null);
lv = (ListView) findViewById(R.id.lv);
lv.setAdapter(new SimpleCursorAdapter(this,R.layout.item_layout,cursor,
new String[]{"_id","name","gender","age"},new int[]{R.id.tv_id,R.id.tv_name,R.id.tv_gender,R.id.tv_age}));
}
运行结果:

上面使用到了SimpleCursorAdapter这个Adapter类,其构造的参数说明:
第一个参数指明应用上下文实例
第二个参数指明ListView中每个条目显示的布局id
第三个参数指明存放要显示数据的Cursor结果集对象
第四和第五个参数共同指明Cursor结果集中每一个字段放在布局文件中的那个控件中,这两个数组中的元素时按顺序一一对应的。第四个参数是String[]类型的,每个元素为结果集中的字段名,第五个参数时int[]类型的,每个参数时布局文件中每个控件的资源id。
在这里需要特别注意的一点是,SimpleCursorAdapter要求表中必须存在名为_id的字段,否则会报错,从而停止正常运行。
但是我之前所建立的表中并没有_id字段,id字段倒是有一个,但是又不想去改变表的定义,这时,就可以在query()方法中,用于指定要查询的字段的第二个参数中使用别名:如上面的写法是:
Cursor cursor = getContentResolver().query(uri, new String[]{"id as _id","name","gender","age"}, null, null, null);
这样结果集中的字段名就由id变为了_id,SimpleCursorAdapter就能正常使用了。
但是,此时由充当应用C角色的应用通过insert()方法添加数据,当前应用中的ListView并没有变化,还是显示不完整的历史数据!!!
针对这个问题,android提供了一个名为ContentObserver的类,用于观察特定uri的数据有无变化,有变化时,则可以根据自己需要做相应的处理。
ContentObserver的使用:

第一步:在应用B中注册ContentObserver,声明要观察的uri,并重写其onChange方法完成需要的业务逻辑。
具体代码如下:
uri = Uri.parse("content://cn.csc.content_provider/t_student");
getContentResolver().registerContentObserver(uri, true, new ContentObserver(new Handler()) {
@Override
public void onChange(boolean selfChange) {
// TODO Auto-generated method stub
super.onChange(selfChange);
Log.i("Test","changed");
Cursor cursor = getContentResolver().query(uri, new String[]{"id as _id","name","gender","age"}, null, null, null);
lv = (ListView) findViewById(R.id.lv);
lv.setAdapter(new SimpleCursorAdapter(MainActivity.this,R.layout.item_layout,cursor,
new String[]{"_id","name","gender","age"},new int[]{R.id.tv_id,R.id.tv_name,R.id.tv_gender,R.id.tv_age}));
Toast.makeText(MainActivity.this, "数据有变化,已然刷新ListView显示", Toast.LENGTH_SHORT).show();
}
});
第二步:在应用A中的insert()、update()、delete()方法中,通知观察这些uri的内容观察者,告知数据发生变化,会触发其对应的onChange方法,完成数据变化的业务。
具体代码如下:
getContext().getContentResolver().notifyChange(uri, null);
当前ListView状态:

在应用C中测试增删改方法,观察应用B中的运行:
增:
public void testInsert(){
Uri uri = Uri.parse("content://cn.csc.content_provider/t_student");
ContentValues values = new ContentValues();
values.put("name", "csc");
values.put("gender", "male");
values.put("age", 25);
Uri uri2 = getContext().getContentResolver().insert(uri, values);
Log.i("Test",uri2.toString());
}
运行结果:

删:
public void testDelete(){
Uri uri = Uri.parse("content://cn.csc.content_provider/t_student");
int i = getContext().getContentResolver().delete(uri, "id>?", new String[]{"7"});
Log.i("Test",i+"");
}
运行结果:

改:
public void testUpdate(){
Uri uri = Uri.parse("content://cn.csc.content_provider/t_student");
ContentValues values = new ContentValues();
values.put("name", "dqrcsc");
values.put("gender", "male");
values.put("age", 24);
int i = getContext().getContentResolver().update(uri, values, "id>?", new String[]{"3"});
Log.i("Test",i+"");
}
运行结果:

以上,就是ContentObserver的简单使用啦。
android菜鸟学习笔记22----ContentProvider(二)ContentObserver的简单使用的更多相关文章
- android菜鸟学习笔记7----android布局(二)
3.FrameLayout:帧布局 如同Flash或者photoshop中图层的概念,在上面的图层遮盖下面的图层,没被遮到的地方仍然显示出来. 右击res/layout,然后在弹出的菜单中选择new, ...
- android菜鸟学习笔记23----ContentProvider(三)利用内置ContentProvider监听短信及查看联系人
要使用一个ContentProvider,必须要知道的是它所能匹配的Uri及其数据存储的表的结构. 首先想办法找到访问短信及联系人数据的ContentProvider能接受的Uri: 到github上 ...
- android菜鸟学习笔记21----ContentProvider(一)ContentProvider的简单使用
ContentProvider是Android四大组件之一,它用来封装数据,并通过ContentResolver接口将数据提供给其他应用.只有当需要在多个应用之间共享数据时才会用到ContentPro ...
- android菜鸟学习笔记31----Android使用百度地图API(二)获取地理位置及地图控制器的简单使用
1.获取当前地理位置: Android中提供了一个LocationManager的类,用于管理地理位置.不能通过构造函数获取该类的实例,而是通过Context的getSystemService(): ...
- android菜鸟学习笔记25----与服务器端交互(二)解析服务端返回的json数据及使用一个开源组件请求服务端数据
补充:关于PHP服务端可能出现的问题: 如果你刚好也像我一样,用php实现的服务端程序,采用的是apache服务器,那么虚拟主机的配置可能会影响到android应用的调试!! 在android应用中访 ...
- android菜鸟学习笔记13----Android控件(二) 自定义控件简单示例
有时候,可能觉得系统提供的控件太丑,就会需要自定义控件来实现自己想要的效果. 以下主要参考<第一行代码> 1.自定义一个标题栏: 系统自带的标题栏很丑,且没什么大的作用,所以我们之前会在o ...
- android菜鸟学习笔记9----Activity(二)
关于Activity的生命周期: 下面是Activity整个生命周期中,状态发生变化时所回调的方法,它们对应着Activity完整的生命过程. void onCreate(Bundle savedI ...
- android菜鸟学习笔记18----Android数据存储(二)SharedPreferences
数据存储的方式,有比直接文件读写更加简便的方式,那就是操作SharedPreferences. SharedPreferences一般用于存储用户的偏好设定,暂时不支持多进程操作. SharedPre ...
- android菜鸟学习笔记30----Android使用百度地图API(一)准备工作及在应用中显示地图
1.准备工作: 百度地图API是免费开放的,但是需要申请API Key: 1)先注册一个百度开发者帐号 2)进入百度开放服务平台http://developer.baidu.com/ 3)进入LBS云 ...
随机推荐
- osgconv使用指南(转)
osgconv是一种用来读取3D数据库以及对它们实施一些简单的操作的实用应用程序,同时也被称作 一种专用3D数据库工具. 用osgconv把其他格式的文件转换为OSG所支持的格式 osgconv是一种 ...
- hibernate中对象的3种状态:瞬时态(Transient)、 持久态(Persistent)、脱管态(Detached)
Hibernate的对象有3种状态,分别为:瞬时态(Transient). 持久态(Persistent).脱管态(Detached). 处于持久态的对象也称为PO(Persistence Objec ...
- zabbix_sender高效模式
1.zabbix_sender介绍 zabbix获取key值有超时时间,如果自定义的key脚本一般需要执行很长时间,这根本没法去做监控,获取数据有超时时间,如果一些数据需要执行比较长的时间才能获取的话 ...
- vscode - 添加背景图片
首先,Ctrl+Shift+P安装backround , 而后重启vscode会有默认的背景图片 修改背景图,可自定义三张 具体请看gif图 最开始时,发现png根本不是全透明,用ps处理了一下(下列 ...
- Ubuntu 开机引导文件 /etc/default/grub
# If you change this file, run 'update-grub' afterwards to update # /boot/grub/grub.cfg. GRUB_DEFAUL ...
- 【VBA】隐藏正在使用的工作簿
正在使用的工作簿,嫌窗口太多,不利于操作,想把窗口隐藏,该怎么做呢? Public Sub 隐藏正在使用的工作簿() Application.Visible = False MsgBox " ...
- httpModules 与 httpHandlers
ASP.NET对请求处理的过程:当请求一个*.aspx文件的时候,这个请求会被inetinfo.exe进程截获,它判断文件的后缀(aspx)之后,将这个请求转交给ASPNET_ISAPI.dll,AS ...
- python 三个双引号
有的内容被上面三个双引号和下面三个双引号包围了,这些内容不执行.即,下面aaa的部分不执行. """ aaaa; """
- python random 学习
随机产生8位数,每位数都是1~6之间数字 import random list_1 = [i for i in xrange(1,7)] print list_1 arr_1=[] for i in ...
- Iocomp控件教程之LinearGauge--线性刻度尺控件
线性刻度尺-线性刻度尺控件(LinearGauge)是一个具有线性表达式刻度的图像控件.支持多达5种颜色断面和4种指示器样式,相同功能,查看线性对数刻度尺(Linear Log Gauge)控件内容 ...