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);
      }
是不是简单的不要不要的~主要还是看自己的理解以及动手实践,让我们一起进步吧~

在一个千万级的数据库查寻中,如何提高查询效率?

1)数据库设计方面: a. 对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。 b. 应尽量避免在 where 子句中对字段进行 null 值...
  • u010870518
  • u010870518
  • 2015年03月09日 16:42
  • 26776

提升数据库数据查询效率

1. 前言随着信息技术的发展,信息系统在企业中的应用也越来越广泛,信息系统在企业运营中扮演者十分重要的角色。可以说在信息化如此广泛的今天,企业信息化是提升企业运营效率的必经之路,数据是企业资产中必不可...
  • sinat_36246371
  • sinat_36246371
  • 2016年10月29日 08:29
  • 395

数据库提高查询效率(较大数据)优化方法

1、数据库设计方面: (1)建立索引 (2)分区(MySQL,如按时间分区) (3)尽量使用固定长度字段和限制字段长度。(如VARCHAR2(10);优势:①降低物理存储空间 ②提高数据库处理速...
  • u011587361
  • u011587361
  • 2015年08月01日 15:31
  • 2005

Android MVPBuilder第三篇[GreenDao]

- [ MVPBuilder Github 下载地址]今天我们引入数据库开源框架GreenDao,它是非常优秀的ORM框架。先来看看今天要关注的工程目录结构: 就是箭头所指的那几个文件。其中只有...
  • yihukurama
  • yihukurama
  • 2016年08月09日 16:58
  • 222

数据库查询效率

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

Android ORM 框架之GreenDAO(二) 进阶

Android ORM 框架之 GreenDAO(一) 简单使用 这篇文章讲解了使用 GreenDAO创建DAO以及使用该DAO创建数据库、表等,没有涉及过多的数据库操作以及更新,今天就来看看Gree...
  • zxw136511485
  • zxw136511485
  • 2016年10月08日 17:53
  • 1225

四种高效数据库设计思想——提高查询效率

【开篇】设计数据库表结构时,我们首先要按照数据库的三大范式进行建立数据库。 1. 1NF每列不可拆分 2. 2NF确保每个表只做一件事情 3. 3NF满足2NF,消除表中的...
  • mrlin6688
  • mrlin6688
  • 2016年12月11日 16:54
  • 1288

Three.js进阶篇之1 - 网格

在学习了几何形状和材质之后,我们就能使用他们来创建物体了。最常用的一种物体就是网格(Mesh),网格是由顶点、边、面等组成的物体;其他物体包括线段(Line)、骨骼(Bone)、粒子系统(Partic...
  • linolzhang
  • linolzhang
  • 2017年03月27日 23:38
  • 785

Java进阶篇

这篇博客主要记录在写Java过程中遇到的一系列问题 问题的解答会引用大牛们的解答或者博客,同样会一直更新下去... 1.如果在一个方法类里定义了一个内部类(比如匿名类),那么该内部类不能引用该方法...
  • u012866104
  • u012866104
  • 2015年12月20日 22:25
  • 443

B-Tree作为索引能够提高查询效率的原理

要说明这个原理,首先要知道局部性原理:当一个数据被用到时,其附近的数据也通常会马上被使用。程序运行期间所需要的数据通常比较集中。 有了局部性原理,操作系统磁盘的访问方式就改变了,访问数据的时候不是...
  • coder_panyy
  • coder_panyy
  • 2017年04月08日 23:26
  • 332
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Android数据库查询效率进阶篇
举报原因:
原因补充:

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