关闭

Android数据库查询效率进阶篇

标签: Android 笔记
386人阅读 评论(0) 收藏 举报

    前言:人外有人,天外有天。不得不佩服那些能写出高效率代码的大神,跟他们的代码逻辑一比较,真的是......唉,不忍直视,但是千万不要灰心丧气,我们这些小喽罗要做的就是理解他们的思路并实时做总结,最后吸收为自己的东西,这篇是关于使用ContentReslover查询数据的,真的算是一种进阶吧,我边上代码边跟大家解释吧~

    我们都是知道数据库里面有很多的表,比如sms的数据库,有contact的数据库等等很多,有时候你要做的是查询第一张表的结果要作为查询第二张表的条件,比如:查询短信黑名单时,你可以获取到号码,短信内容,ID,日期之类的,但是要获取号码对应的联系人姓名时,你就得根据号码来查询联系人数据库了(有的小伙伴说,短信数据库不是有person字段么,有必要查询联系人表么?那么我可以负责人的告诉你,很有可能,person返回的是null,具体的原因可以上网查找),那么现在就跟着一步一步的看吧~

First Version

Cursor cur =context.getContentResolver().query(builder.build(), null, null, null, "date DESC");
	if(cur != null){
		try {
			if(cur.moveToFirst()){
				int index_id = cur.getColumnIndex(SMS_DB_ID);
				int index_number = cur.getColumnIndex(SMS_DB_NUMBER);
				int index_content = cur.getColumnIndex(SMS_DB_CONTENT);
				int index_date = cur.getColumnIndex(SMS_DB_DATE);
				int index_category = cur.getColumnIndex(SMS_DB_CATEGORY);
					do {
						smsItems.add(
							new SmsItem(
								cur.getInt(index_id),
								cur.getString(index_number),
								cur.getString(index_content),
								cur.getLong(index_date),
								cur.getInt(index_category)));
                                } while (cur.moveToNext());

以上就是我查询的短信数据库的一些信息,最终存放到smsItems这个列表当中,接下来,我要去根据smsItems中每一个数据号码去查询联系人表中的数据

String SMS_DATA = "data1 = ?";
StringBuilder contactsSelections = new StringBuilder();
String contactsSelectionArgs[] = new String[smsItems.size()];
	for(int i = 0; i < smsItems.size();i++){
		if(i == smsItems.size() -1){
		contactsSelections.append(SMS_DATA);
	}else{
		contactsSelections.append(SMS_DATA +  " OR ");
	}
		contactsSelectionArgs[i] = smsItems.get(i).getNumber();
	}

以上是拼接字符串,用来查询联系人表中符合条件的语句,下面进行正式的查询了

ContentResolver smsResolver = context.getContentResolver();
Cursor contatcCursor = smsResolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,contactsSelections.toString,contactsSelectionArgs,null.null);
	 if (contatcCursor.moveToFirst()) {  
		 do{
			 name = contatcCursor.getString(contatcCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)); 
			 number = contatcCursor.getString(contatcCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));						
			  for(int i = 0;i < smsItems.size();i++){
				 if (smsItems.get(i).getNumber().equals(contactNumber)) {
					smsItems.get(i).setName(contactName);
					 }
				}
		  } while(contatcCursor.moveToNext());} 
			contatcCursor.close();  
			} 
然后将每一项的数据绑定并进行显示,对,这就是第一个版本,是不是感觉跟你的写法很像,正常,我第一次也是这么写的,现在我们进行修改

Second Version

这个版本修改的内容很少,因为大神粗略的看了一下,“你这个sql语句拼写的太长啦,你可以试试in这个关键字”,然后我二话不说,立马百度了sql in 的关键字,修改如下:

	StringBuilder contactsSelections = new StringBuilder();
	for(int i = 0; i < smsItems.size();i++){
		if(i == smsItems.size() -1){
		contactsSelections.append(smsItems.get(i).getNumber());
		}else{
		contactsSelections.append(smsItems.get(i).getNumber() +  ",");
			}
		}
<span style="font-size:14px;"><strong>Cursor contatcCursor = smsResolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,null,ContactsContract.CommonDataKinds.Phone.NUMBER +"("+contactsSelections+")",null, null);</strong></span>
果然,改了之后去除了一个字符串数组,正当我得意的把代码给大神看的时候,“恩,不错,是修改了,但是这个smsItems中会有重复的数据吧,在你进行绑定的时候,岂不是又要重新循环一次?这样不怎么效率啊,可以有更好的写法,可以考虑这个Map<KeyType, List<ValueType>>"我当时就傻了,我说这个结构我哪知道啊,只能硬着头皮琢磨了1天,还是没有整出来,最后还是虚心请教大神~

Third Version

首先得声明一个类

 private static class Multimap<K,V> {
		 
	        private HashMap<K,List<V>> store = new HashMap<K,List<V>>();
	        List<V> getAll(K key) {
	            List<V> values = store.get(key);
	            return values != null ? values : Collections.<V>emptyList();
	        }        
	        
	        void put(K key, V val) {
	            List<V> curVals = store.get(key);
	            if (curVals == null) {
	                curVals = new ArrayList<V>(3);
	                store.put(key, curVals);
	            }
	            curVals.add(val);
	        } 
	        
	        Set<K> getAllKey() {
	        	return store.keySet();
	        }
	    }
看看这个代码结构,跟我这种小学生写的完全不是一个境界的嘛,这个先暂时不说,看下面如何使用这个~

Multimap<String, SmsItem> map = new Multimap<String, SmsItem>();

声明,其中将类型替换成自己学要的,不多说了

do {
    SmsItem smsItem = new SmsItem(
				cur.getInt(index_id),
				cur.getString(index_number),
				cur.getString(index_content),
				cur.getLong(index_date),
				cur.getInt(index_category));
   smsItems.add(smsItem);
   map.put(smsItem.getNumber(), smsItem);
}while(cur.moveToNext())

这个地方就是使用这个结构了,每个号码对应一个smsItem,如果有相同的号码,则把第二个smsItem中的所有信息放入到List中,这个都有实现的

再来看看,如何方便的拼接字符串吧~

String contactsSelections = null; 
String[] phoneNumbers = map.getAllKey().toArray(new String[map.getAllKey().size()]);
contactsSelections = TextUtils.join(",", phoneNumbers);
就是这么短,还需要什么for循环,以后千万不要用for循环来拼接了,太low啦~

最后,我们看如何进行数据的绑定~

 for(SmsItem s: map.getAll(number)){
     s.setName(name);
      }
是不是简单的不要不要的~主要还是看自己的理解以及动手实践,让我们一起进步吧~

0
0

猜你在找
【直播】机器学习&数据挖掘7周实训--韦玮
【套餐】系统集成项目管理工程师顺利通关--徐朋
【直播】3小时掌握Docker最佳实战-徐西宁
【套餐】机器学习系列套餐(算法+实战)--唐宇迪
【直播】计算机视觉原理及实战--屈教授
【套餐】微信订阅号+服务号Java版 v2.0--翟东平
【直播】机器学习之矩阵--黄博士
【套餐】微信订阅号+服务号Java版 v2.0--翟东平
【直播】机器学习之凸优化--马博士
【套餐】Javascript 设计模式实战--曾亮
查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:4017次
    • 积分:147
    • 等级:
    • 排名:千里之外
    • 原创:10篇
    • 转载:1篇
    • 译文:0篇
    • 评论:0条