Android数据库查询效率进阶篇

原创 2015年11月19日 17:28:43

    前言:人外有人,天外有天。不得不佩服那些能写出高效率代码的大神,跟他们的代码逻辑一比较,真的是......唉,不忍直视,但是千万不要灰心丧气,我们这些小喽罗要做的就是理解他们的思路并实时做总结,最后吸收为自己的东西,这篇是关于使用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);
      }
是不是简单的不要不要的~主要还是看自己的理解以及动手实践,让我们一起进步吧~

提高Oracle数据库查询效率

  • 2012年09月21日 12:14
  • 5KB
  • 下载

提高数据库查询效率的八个方法

当用户在一张大表中采用这个LIKE语句的话,就会发现这个查询语句的运行效率非常的慢。这是什么原因造成的呢?其实,不管是Like 关键字,若采用MATCHES关键字的话,若在大量数据中查找符合条件的记录...
  • yhd0916
  • yhd0916
  • 2016年10月23日 19:44
  • 218

分享一篇幅提高MySQL数据库查询效率的技巧文章大家欣赏

MySQL数据库由于它本身的小巧和操作的高效, 在数据库应用中越来越多的被采用.我在开发一个P2P应用的时候曾经使用MySQL来保存P2P节点,由于P2P的应用中,结点数动辄上万个…… ...

详细讲解提高数据库查询效率的实用方法

1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。   2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引...
  • love560
  • love560
  • 2012年09月11日 16:40
  • 246

提高数据库查询效率的简单常用方法

1、 Where子句中条件的顺序对性能没有影响,注意,额外说一下,这里只是说条件的顺序,不包含表的顺序。在RBO优化器模式下,表应按结果记录数从大到小的顺序从左到右来排列,因为表间连接时,最右边的表会...

提高数据库查询效率的有效方法

点击打开链接       1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。     2.应尽量避免在 where 子句...

[转]详细讲解提高数据库查询效率的实用方法、外键关于性能

1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。 2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用...
  • WXDZXL
  • WXDZXL
  • 2012年09月27日 14:26
  • 812

数据库查询效率

详细讲解提高数据库查询效率的实用方法 1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。   2.应尽量避免在 where 子句中...
  • sxqzxj
  • sxqzxj
  • 2015年05月19日 18:24
  • 290

详细讲解提高数据库查询效率的实用方法、外键关于性能【转】

1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。 2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Android数据库查询效率进阶篇
举报原因:
原因补充:

(最多只允许输入30个字)