3.CursorAdapter
会话页面




public class ConversationUI extends Activity implements OnItemClickListener, OnClickListener{private ListView listView;private Button btnNewMessage;private Button btnSelectAll;private Button btnSelectNull;private Button btnDeleteMsg;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_conversation);this.ctx = this;init();flushState();prepareData();}/*** 要查询的列*/private String[] projection={"sms.body AS snippet","sms.thread_id AS _id",//需要主键可是没有,可以起个别名"groups.msg_count AS msg_count","address as address","date as date"};/*** 短信内容所在列的索引值 为 0*/private final int INDEX_BODY = 0;/*** 会话ID所在列的索引值 为 1*/private final int INDEX_THREAD_ID = 1;/*** 短信数量所在列的索引值 为 2*/private final int INDEX_MSG_COUNT = 2;/*** 短信联系人电话所在列的索引值 为 3*/private final int INDEX_ADDRESS = 3;/*** 短信日期所在列的索引值 为 4*/private final int INDEX_DATE = 4;/*** 给listView 准备数据*/private void prepareData() {/** 查询数据库,如果数据太多了,会造成ANR异常,所 以,一般都会开子线程,查询数据,然后,用handler将结果,回传*/MyQueryHandler queryHandler = new MyQueryHandler(getContentResolver());queryHandler.startQuery(234, adapter, MyConstants.URI_CONVERSATION, projection, null, null, " date desc");//按日期倒序查询}private void init() {btnNewMessage = (Button) findViewById(R.id.btn_new_message_conversation);btnSelectAll = (Button) findViewById(R.id.btn_select_all_conversation);btnSelectNull = (Button) findViewById(R.id.btn_select_null_conversation);btnDeleteMsg = (Button) findViewById(R.id.btn_delete_message_conversation);btnNewMessage.setOnClickListener(this);btnSelectAll.setOnClickListener(this);btnSelectNull.setOnClickListener(this);btnDeleteMsg.setOnClickListener(this);listView = (ListView) findViewById(R.id.lv_conversation);adapter = new MyListAdapter(this, null);//可以先传个nulllistView.setAdapter(adapter);listView.setOnItemClickListener(this);selectItemSet = new HashSet<Integer>();//删除时选中的集合}private boolean isEditState = false;private void flushState() {if(isEditState){//编辑状态btnNewMessage.setVisibility(View.GONE);btnSelectAll.setVisibility(View.VISIBLE);btnSelectNull.setVisibility(View.VISIBLE);btnDeleteMsg.setVisibility(View.VISIBLE);}else{//非编辑状态btnNewMessage.setVisibility(View.VISIBLE);btnSelectAll.setVisibility(View.GONE);btnSelectNull.setVisibility(View.GONE);btnDeleteMsg.setVisibility(View.GONE);}//判断listview 的条目是否有被选中,如果没有被选中的,btnSelectNull 和 btnDeleteMsg 应该处于不可用的状态 否则,是可用的状态if(selectItemSet.size()==0){// listview条目没有被选择btnSelectNull.setEnabled(false);btnDeleteMsg.setEnabled(false);}else{btnSelectNull.setEnabled(true);btnDeleteMsg.setEnabled(true);}// 根据 selectItemSet 集合当中的内容数量,改变 全选按钮的状态// 判断 selectItemSet 的size 和listView的条目数量,是否相同,如果相同,全选按钮,就不可用。if(selectItemSet.size() == adapter.getCount()){btnSelectAll.setEnabled(false);}else{// 否则,是可用的btnSelectAll.setEnabled(true);}}private MyListAdapter adapter ;public Context ctx;class MyListAdapter extends CursorAdapter{public MyListAdapter(Context context, Cursor c) {super(context, c);}@Override/*** 当 conterView是null时,需要用户创建view 的时候调*/public View newView(Context context, Cursor cursor, ViewGroup parent) {View view = View.inflate(ctx, R.layout.list_item_conversation,null);ViewHolder vh = new ViewHolder();vh.checkbox = (ImageView) view.findViewById(R.id.iv_checkbox_list_item);vh.face = (ImageView) view.findViewById(R.id.iv_face_list_item);vh.address = (TextView) view.findViewById(R.id.tv_address_list_item);vh.body = (TextView) view.findViewById(R.id.tv_body_list_item);vh.date = (TextView) view.findViewById(R.id.tv_date_list_item);view.setTag(vh);return view;}@Override/*** 为itemview设置内容时调用* view 即 newView 方法的返回值*/public void bindView(View view, Context context, Cursor cursor) {ViewHolder vh = (ViewHolder) view.getTag();//显示短信内容vh.body.setText(cursor.getString(INDEX_BODY));//显示日期:long when = cursor.getLong(INDEX_DATE);String dateStr;//使用系统工具类,判断是否是今天if(DateUtils.isToday(when)){dateStr = DateFormat.getTimeFormat(ctx).format(when);}else{dateStr = DateFormat.getDateFormat(ctx).format(when);}vh.date.setText(dateStr);//显示联系人地址:String number = cursor.getString(INDEX_ADDRESS);int msgcount = cursor.getInt(INDEX_MSG_COUNT);// 获得短信的数量String name = Tools.findNameByNumber(ctx, number);if(name == null){//表明无此联系人vh.address.setText(number+"("+msgcount+")");}else{vh.address.setText(name+"("+msgcount+")");}//显示联系人的头像:// 根据电话号码,查询联系人IDint contactId = Tools.findIDByNumber(ctx, number);// 如果 ID = -1 表明,无此联系人,此时,应设置一个 未知的联系人头像if(contactId == -1){vh.face.setBackgroundResource(R.drawable.ic_unknow_contact_picture);}else{// 根据ID 获得联系人头像,Bitmap bitmap = Tools.getFaceById(ctx, ""+contactId);//如果 bitmpa == null 表明,此联系人,无头像,应设置,一个联系人的默认的头像if(bitmap == null){vh.face.setBackgroundResource(R.drawable.ic_contact_picture);}else{//否则,将bitmap 设置为联系人的头像vh.face.setBackgroundDrawable(new BitmapDrawable(bitmap));}}/** 设置 checkBox*///如果是编辑状态,显示checkBox,if(isEditState){vh.checkbox.setVisibility(View.VISIBLE);// 该条目对应的会话IDint threadId = cursor.getInt(INDEX_THREAD_ID);//判断集合当中,是否有该条目对应的会话ID,如果有,表示是选中状态,如果没有,是没选中状态。if(selectItemSet.contains(threadId)){vh.checkbox.setEnabled(true);}else{vh.checkbox.setEnabled(false);}}else{//否则,隐藏vh.checkbox.setVisibility(View.GONE);}}}/*** 存储在编辑状态下,选中的listView的条目*/private HashSet<Integer> selectItemSet;class ViewHolder{public ImageView checkbox;public ImageView face;public TextView address;public TextView body;public TextView date;}@Override/*** 第一次点击menu按键时,调用,用于创建菜单选 项*/public boolean onCreateOptionsMenu(Menu menu) {menu.add(0, ID_SEARCH, 0, "搜索");menu.add(0, ID_EDIT, 0, "编辑");menu.add(0, ID_CANCEL_EDIT, 0, "取消编辑");return true;}private final int ID_SEARCH=100;private final int ID_EDIT=101;private final int ID_CANCEL_EDIT=102;@Override/*** 每次按menu按键的时候,调用,做一些准备工作*/public boolean onPrepareOptionsMenu(Menu menu) {if(isEditState){//如果是编辑状态menu.findItem(ID_EDIT).setVisible(false);menu.findItem(ID_SEARCH).setVisible(false);menu.findItem(ID_CANCEL_EDIT).setVisible(true);}else{menu.findItem(ID_EDIT).setVisible(true);menu.findItem(ID_SEARCH).setVisible(true);menu.findItem(ID_CANCEL_EDIT).setVisible(false);}return true;}@Override/*** 当选择某一个菜单时,调用*/public boolean onOptionsItemSelected(MenuItem item) {switch (item.getItemId()) {case ID_SEARCH:break;case ID_EDIT: // 编辑菜单isEditState = true;flushState();break;case ID_CANCEL_EDIT: //取消编辑isEditState = false;//清空集合selectItemSet.clear();flushState();break;}return true;}@Override/*** 响应listview的条目点击事件*/public void onItemClick(AdapterView<?> parent, View view, int position,long id) {//通过adapter 获得cursorCursor cursor = adapter.getCursor();//将cursor移动到对应的位置cursor.moveToPosition(position);//取得该位置对应的会话IDint threadId = cursor.getInt(INDEX_THREAD_ID);if (isEditState) {// 判断 集合中是否有该会话ID,如果有,就删除,如果没有,就添加if (selectItemSet.contains(threadId)) {selectItemSet.remove(threadId);} else {selectItemSet.add(threadId);}//刷新listviewadapter.notifyDataSetChanged();//刷新按钮状态flushState();}else{String address = cursor.getString(INDEX_ADDRESS);Intent intent = new Intent(this,ConversationDetail.class);intent.putExtra("address", address);// 将当前条目对应的联系人电话号码,传递给会话详情页面startActivity(intent);}}@Override/*** 响应按钮的点击事件* @param v*/public void onClick(View v) {switch (v.getId()) {case R.id.btn_delete_message_conversation://显示确认删除的对话框showConfirmDeleteDialog();break;case R.id.btn_new_message_conversation:// 点击新建信息按钮时,响应Intent intent = new Intent(this,NewMessageUI.class);startActivity(intent);break;case R.id.btn_select_all_conversation: // 全选按钮Cursor cursor = adapter.getCursor();cursor.moveToPosition(-1);while(cursor.moveToNext()){int threadId = cursor.getInt(INDEX_THREAD_ID);selectItemSet.add(threadId); // set集合的特点:无序,不可重置,如果添加的内容之前已经有了,会覆盖。}//刷新listviewadapter.notifyDataSetChanged();// 刷新状态flushState();break;case R.id.btn_select_null_conversation: // 取消选择的按钮//清空集合selectItemSet.clear();//刷新listviewadapter.notifyDataSetChanged();// 刷新状态flushState();break;}}/*** 显示确认删除的对话框*/private void showConfirmDeleteDialog() {AlertDialog.Builder adb = new AlertDialog.Builder(this);adb.setTitle("清除短信");adb.setMessage("确认删除这些回忆吗?");adb.setNegativeButton("确认", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {// 开子线程,删除短信,new Thread(new DeleteMsgRunnable()).start();// 显示删除短信的进度对话框showDeleteProgressDialog();}});adb.setPositiveButton("取消", null);adb.show();}private ProgressDialog proDlg;/*** 显示删除短信的进度对话框*/protected void showDeleteProgressDialog() {proDlg =new ProgressDialog(this);proDlg.setTitle("正在删除短信");//设置 进度框 为水平显示的样式,proDlg.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);// 设置进度条的最大值 = 集合的大小。proDlg.setMax(selectItemSet.size());proDlg.setButton("取消", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {isCancelDeleteMsg = true;}});// 给进度框添加,关闭时的回调 ,监听,监听的代码,会在UI线程中执行proDlg.setOnDismissListener(new DialogInterface.OnDismissListener() {@Overridepublic void onDismiss(DialogInterface dialog) {isEditState = false;flushState();// 刷新页面状态System.out.println(selectItemSet);adapter.notifyDataSetChanged();// 刷新listviewSystem.out.println("222::"+selectItemSet);}});proDlg.show();}/*** 判断是否取消删除短信*/private boolean isCancelDeleteMsg;class DeleteMsgRunnable implements Runnable{@Overridepublic void run() {// 遍历 selectItemSet 集合,根据会话ID,删除短信for(Integer threadId : selectItemSet ){ // 用增强for循环 遍历 set集合SystemClock.sleep(1000); // 会为显示效果正好,在此休眠一秒,if(isCancelDeleteMsg){break; // 跳出 for 循环}Tools.deleteMsgByThreadId(ctx,threadId);proDlg.incrementProgressBy(1);//让 proDlg 的水平进度条,增加刻度}// 清空集合selectItemSet.clear();// 清空集合//关闭进度框proDlg.dismiss();// 将 isCancelDeleteMsg 复原isCancelDeleteMsg = false;// flushState();// 在子线程中不能更新UI}}}
3.CursorAdapter的更多相关文章
- 在VFP6中模拟CursorAdapter的功能
这个是我在2002年做的一个VFP程序中实现的方法, 现在看来功能和VFP8,9中的CursorAdapter非常相似, 因为属性设置有许多相同的地方,我甚至怀疑CA就是就是在这样的基础上再包装出来的 ...
- AsyncQueryHandler 和 CursorAdapter的使用
AsyncQueryHandler A helper class to help make handling asynchronous ContentResolver queries easier. ...
- Android CursorAdapter
CursorAdapter 继承于BaseAdapter是个虚类,它为cursor和ListView提供了连接的桥梁. public abstract class Cur ...
- AutoCompleteTextView和自定义的CursorAdapter
用雅虎天气接口和AutoCompleteTextView开发天气应用(1) 2014/03/20 | 分类: ANDROID, 开发 | 2 条评论 | 标签: 天气, 安卓开发 分享到:5 jQue ...
- Android开发——利用Cursor+CursorAdapter实现界面实时更新
好久没有更新博客了.不是没时间写,而是太懒.而且感觉有些东西没有时间总结,之之后再想写,就想不起来了.晚上新发现一点东西,所以就及时写下来. 最近利用业余时间在看Android的Download模块, ...
- ContentProvider和Cursor以及CursorAdapter三者之间内部链接实现原理 解析
最近 在学习Android3.0中推出的 Loader 机制,其中CursorLoader 这个加载器说是可以实时监测数据和更新数据,为了一探究竟,就连带的将 ContentProvider和Curs ...
- 【Android】13.2 使用自定义的CursorAdapter访问SQLite数据库
分类:C#.Android.VS2015: 创建日期:2016-02-26 一.简介 SQliteDemo1的例子演示了SimpleCursorAdapter的用法,本节我们将使用用途更广的自定义的游 ...
- CursorAdapter中getView newView bindView异同
Adapter的作用是界面与数据之间的桥梁,通过设置适配器至ListView控件后(如调用ListView的 setAdapter(ListAdapter adapter) ...
- Android如果动态改变CursorAdapter Item个数
//adapter内部类 private class SearchAdapter extends CursorAdapter { @Override public View newView(Conte ...
随机推荐
- AutoMapper 忽略某个字段
以前要在定义中忽略 Mapper.CreateMap<Source, Destination>() .ForMember(dest => dest.SomeValuefff, opt ...
- 使用react-handsontable
新建一个项目 create-react-app myProject cd myProject npm install handsontable 或者 npm install handsontable- ...
- 多个表左联,要返回全部的结果,解决不能用where的问题
qb.leftJoin('info_student', 'grouping_class_student.studentId', 'info_student.id'); qb.leftJoin('gro ...
- 视频剪辑软件原型-videocut
制作软件:墨刀 分享网址:<iframe src="https://modao.cc/app/fb0e31590711295ebebdf50fff7dd9861b7a9c1d/embe ...
- python3 安装 basemap 包(windows10)
下载 pyproj 和 basemap 的安装包 basemap 是具有专业标准的地图绘制工具,可以与 matplotlib 的一般绘图功能结合,在地图上绘制数据. basemap 文档:https: ...
- Altium Designer 16 问题解决
1:同一个工程中,不同原理图里的网络标号不能关联起来 解决---> 选择 工程->工程参数->网络识别符范围 -> GLOBAL 2:PCB中影藏显示相应Net的飞线 解 ...
- SAS 函数
SAS 函数 SAS函数是编程语言的一个组件,可接受参数.执行计算或进行其他操作并返回值.返回值是字符型或数值型的结果,可用于赋值语句或 表达式中.SAS包含很多函数,也可以自定义函数.在BASE S ...
- uiautomatorviewer报错“Error taking device screenshot: EOF” ,
uiautomatorviewer报错“Error taking device screenshot: EOF” ,千万不要装手机助手,不要装手机助手,不要装手机助手 uiautomatorview ...
- 第50章:Java操作MongoDB-MongoDB和Spring
① Spring通过Spring Data MongoDB模块来集成和支持MongoDB ②Maven加入lib包 <dependency> <groupId>org.spri ...
- Codeforces Round #485 (Div. 2) C. Three displays
Codeforces Round #485 (Div. 2) C. Three displays 题目连接: http://codeforces.com/contest/987/problem/C D ...