一、ListView
1.XML布局
- 在main.xml中声明ListView标签
- 定义一个新的item.xml布局, 描述每个条目<TextView />的布局
2.构建ListView
- 获取ListView
- 设置适配器(三种)setAdapter(ListAdapter)
- BaseAdapter *
- 定义类继承BaseAdapter, 重写4个抽象方法
- getView()方法是获取指定位置上的View视图, 在该方法中根据新建的xml布局生成LinearLayout, 获取其中的TextView, 设置文本
- BaseAdapter *
- SimpleAdapter
- 创建SimpleAdapter, 传入数据List<Map<String, Object>>, 传入布局文件, 映射关系
- SimpleCursorAdapter
- 创建SimpleCursorAdapter, 传入布局文件, 数据Cursor, 映射关系
3.ListView点击事件处理 *
- 调用setOnItemClickListener()方法添加监听器
- 在监听器中调用parent.getItemAtPosition(position)
BaseAdapter得到自定义的getItem()方法返回的对象
SimpleAdapter得到指定位置上的Map
SimpleCursorAdapter得到一个移动到指定位置的Cursor
二.内容提供者 *****
1.什么是内容提供者
可以共享数据的一个组件
数据不直接暴露, 通过方法访问, 提高安全性
可以在应用中对指定的内容提供者注册观察者, 观察其数据修改
2.定义内容提供者
定义类继承ContentProvider, 重写抽象方法
清单文件中定义<provider>节点, 定义name属性指定类名, 定义authorities属性指定访问时的路径
3.访问内容提供者
获取ContentResolver对象, 调用ContentResolver的query(),insert()等方法对指定的Uri进行操作
4.细节补充
在ContentProvider中的query(),insert(),delete(),update()方法中可以对数据进行操作, 通常都是操作数据库
如果需要匹配Uri后的子级路径, 可以使用UriMatcher类, addUri()方法添加一个可识别的Uri, match()方法识别Uri
截取id和追加id使用ContentUris完成
5.添加观察者
我们可以对内容提供者注册一个观察者, 在观察者中定义onChange()方法
当内容提供者中数据修改, 执行notifyChange()方法时, 会自动执行观察者中的onChange()方法
三、问题
- 页面:xml布局、singleline="true" --->设置文本只能占一行
- 代码:BaseAdapter的一下代码 向下滑动时,bottom边的item转换为top的item,替换上下文本,不必重新创建和销毁item
- View view = convertView == null ? (View.inflate(getApplicationContext(), R.layout.item, null)): convertView;
- 常犯错误:上行代码中是view.findViewById(R.id.ageTV);而不是findViewById(R.id.ageTV);
- new SimpleCursorAdapter(getApplicationContext(),R.layout.item, c, new String[]{"_id","name","age"}, new int[]{R.id.idTV,R.id.nameTV,R.id.ageTV}),该适配器只能识别"_id"的列,如果返回Cursor的方法中没有该列,可改变查询语句 new String[]{"id as _id", "name", "age"}
- BaseAdapt 适合复杂的业务,比如处理每个文本控件的事件
- SimpleAdapter、SimpleCursorAdapter 适 用教简单的业务
- ListView添加监听处理
- 添加监听器 personLV.setOnItemClickListener(OnItemClickListener listener );
- 在监听器中 OnItemClick 方法处理:调用parent.getItemAtPosition(position) 根据放入的数据类型不同来返回不同的类型
- 时时刷新数据的问题:调用适配器的 adapter.notifyDataSetChanged();方法,但在这之间需要修改数据库数据
- Toast提示
- 内容提供者 ContentProvider ********
- 创建内容提供者: 自定义类实现 ContentProvider ,重写它的五个方法onCreate()/query()/insert()/update()/delete()/getType()
- 在注册表中注册内容提供者的配置信息: android:name是对应的类名,android:author..是对外提供访问的uri,规范由包名+类名组成
- 自定义类中,在onCreate()中初始化DbHelper,分别调用db.getReader../getWriter...方法完成增删改查
- 限制外界访问,只有uri正确才能操作提供的内容,uri格式为:“content://com.itheima.provider.personprovider/...”
- 在此使用uri匹配器:UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);匹配由我设置好的路径,路径初始化格式有下:
- matcher.addURI("com.itheima.provider","person",ALL_PERSONS);
- matcher.addURI("com.itheima.provider","person/#",PERSON);
- matcher.addURI("com.itheima.provider","insert",INSERT);
- ............
- 在进行增删改查时需要注意的是:int type = matcher.match(Uri uri);
- 查询:根据type设置查询的条件, selection = " id = " + ContentUris.parseId(Uri uri );
- 添加: 根据type设置 要 添加 哪个表 的条件, 返回Uri ContentUris.withAppendedId(uri, id);
- 删改: 根据type设置 删改 的条件, selection = " id = " +ContentUris.parseId(Uri uri );
- String getType()方法: 一条记录返回[vnd.android.cursor.item/person ], 多条记录返回[vnd.android.cursor.dir/person ]
- 设置好以上信息后:调用者在调用时就必须遵照规定传入规范的uri才能操作提供的内容:content://com.itheima.personprovider/person/32
- 内容观察者:ContentResolver
- 创建内容观察者:在主界面的onCreate()方法中
- 注册观察者 : getContentResolver().registerContentObserver(new MyContentObserver());
- 实现接口重写onChange():MyContentObserver实现了ContentObserver接口并重写onChange(boolean change)方法
- 调用查询所有数据和适配器的 persons = dao.queryAll(); adapter.notifyDataSetChanged();方法
- 在内容提供者的增删改方法中 getContext().getContentResolver().notifyChange(Uri uri , null)通知观察者数据修改了
- 创建内容观察者:在主界面的onCreate()方法中
- SmsListener监听短信。
- 下载源码,获得解析sms的路径:Uri uri = Uri.parse("content://sms");
- 注册观察者,getContentResolver().registerContentObserver( new ContentObserver(new Handler()){....});
- 在匿名内部类的onChange(boolean )方法中执行getContentResolver().query(uri,new String[]{"address","date","type","body"},null,null,null);并根据query的返回值Cursor输出查询的信息到控制台.
- 部署应用到模拟器,模拟发送短信即可以截获
- Contacts监听联系人:
- Contacts 数据库结构图
- 下载源码,获得解析 Contacts的路径
- private Uri rawContactsUri = Uri.parse("content://com.android.contacts/raw_contacts");
- private Uri dataUri = Uri.parse("content://com.android.contacts/data");
- public void testRead() { //读
- ContentResolver resolver = getContext().getContentResolver();
- Cursor idCursor = resolver.query(rawContactsUri, new String[]{"_id"}, null, null, null);// 查询raw_contacts表中的所有_id
- while (idCursor.moveToNext()) {
- int id = idCursor.getInt(0);// 获取raw_contacts表_id字段的值
- Cursor dataCursor = resolver.query(dataUri// 用raw_contacts表的_id作为条件, 查询data表
- , new String[] { "mimetype", "data1" }, "raw_contact_id=?", new String[] { id + "" }, null);
- while (dataCursor.moveToNext()) {
- String mimetype = dataCursor.getString(0);
- String data1 = dataCursor.getString(1);
- System.out.println(mimetype + ": " + data1);
- }
- }
- }
- //Batch写
- public void testWriteBatch() throws Exception {
- // 创建4个操作对象(ContentProviderOperation),
- ContentProviderOperation operation1 = ContentProviderOperation.newInsert(rawContactsUri) //
- .withValue("_id", null) //
- .build();
- ContentProviderOperation operation2 = ContentProviderOperation.newInsert(dataUri) //
- .withValueBackReference("raw_contact_id", 0)// 用该组第0号操作的返回值作为value
- .withValue("mimetype", "vnd.android.cursor.item/name") //
- .withValue("data1", "FLX")//
- .build();
- ContentProviderOperation operation3 = ContentProviderOperation.newInsert(dataUri) //
- .withValueBackReference("raw_contact_id", 0)// 用该组第0号操作的返回值作为value
- .withValue("mimetype", "vnd.android.cursor.item/phone_v2") //
- .withValue("data1", "13800098765")//
- .build();
- ContentProviderOperation operation4 = ContentProviderOperation.newInsert(dataUri) //
- .withValueBackReference("raw_contact_id", 0)// 用该组第0号操作的返回值作为value
- .withValue("mimetype", "vnd.android.cursor.item/email_v2") //
- .withValue("data1", "flx@itcast.cn")//
- .build();
- ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>();// 用来装载操作的集合
- Collections.addAll(operations, operation1, operation2, operation3, operation4);// 把4个操作对象装入集合
- ContentResolver resolver = getContext().getContentResolver();
- resolver.applyBatch("com.android.contacts", operations);// 对指定的内容提供者, 应用一批操作
- }