Android 号码查询性能优化

来源:互联网 发布:如何设置淘宝客 编辑:程序博客网 时间:2024/04/30 11:03

Android 号码查询性能优化

Android 
我的需求是做一个快速拨号界面!list列表显示所有联系人Calllog资料!原来的做法在前面的日志中有提到!大概是先查 
Java代码  收藏代码
  1. Cursor phoneCursor = this.managedQuery(  
  2.                 ContactsContract.CommonDataKinds.Phone.CONTENT_URI, nullnull,  
  3.                 nullnull);  

再根据号码来查联系人 
Java代码  收藏代码
  1. if(0 < phoneCursor.getCount()){  
  2.         phoneCursor.moveToFirst();  
  3.   
  4.         // find all contact list  
  5.         while (phoneCursor.getPosition() != phoneCursor.getCount()) {  
  6.             ContactEntity contactentity = new ContactEntity();  
  7.             contactentity.contact_id = phoneCursor  
  8.                     .getLong(phoneCursor  
  9.                             .getColumnIndex(ContactsContract.CommonDataKinds.Phone.CONTACT_ID));  
  10.             contactentity.contacts_phone_type = phoneCursor  
  11.                     .getInt(phoneCursor  
  12.                             .getColumnIndex(ContactsContract.CommonDataKinds.Phone.TYPE));  
  13.             contactentity.contacts_phone_number = phoneCursor  
  14.                     .getString(phoneCursor  
  15.                             .getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)).replace(  
  16.                                     "-""");  
  17.   
  18.             contactCursor = this.managedQuery(  
  19.                     ContactsContract.Contacts.CONTENT_URI, null,  
  20.                     ContactsContract.Contacts._ID + "="  
  21.                             + contactentity.contact_id, nullnull);  
  22.             contactCursor.moveToFirst();  
  23.             contactentity.contacts_display_name = contactCursor  
  24.                     .getString(contactCursor  
  25.                             .getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)).replace(  
  26.                                     "-""");  
  27.   
  28.             Uri uri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI,  
  29.                             contactentity.contact_id);  
  30.             InputStream input = ContactsContract.Contacts.openContactPhotoInputStream(getContentResolver(), uri);  
  31.             if(null != input){  
  32.             contactentity.contact_phone_bmp = BitmapFactory.decodeStream(input);  
  33.             }  
  34.   
  35.             // spell name can  
  36.             contactentity.spellName = PinYin.getInstance(this).getPinyinString(  
  37.                     contactentity.contacts_display_name);  
  38.   
  39.             Log.i(TAG, "contactentity.contact_id: " + contactentity.contact_id  
  40.                     + " contactentity.contacts_phone_type: "  
  41.                     + contactentity.contacts_phone_type  
  42.                     + " contactentity.contacts_phone_number: "  
  43.                     + contactentity.contacts_phone_number  
  44.                     + "contactentity.contacts_display_name: "  
  45.                     + contactentity.contacts_display_name  
  46.                     + "contactentity.contact_phone_bmp: "  
  47.                     + contactentity.contact_phone_bmp);  
  48.             phoneCursor.moveToNext();  
  49.   
  50.             customArrayList.add(contactentity);  
  51.         }  


经过测试发现性能消耗主要在这个while循环当中!因为在循环当中在加一个查询数据库操作自然慢! 

解决方案: 
发现在查询ContactsContract.CommonDataKinds.Phone.CONTENT_URI数据库时其实可以吧 
ContactsContract.Contacts.DISPLAY_NAME, 
ContactsContract.Contacts.PHOTO_ID查询出来 
那么把原来的 

Java代码  收藏代码
  1. private final static String[] mContactsProjection = new String[] {  
  2.             ContactsContract.CommonDataKinds.Phone.CONTACT_ID,  
  3.             ContactsContract.CommonDataKinds.Phone.TYPE,  
  4.             ContactsContract.CommonDataKinds.Phone.NUMBER,  
  5.               
  6.     };  

改为 
Java代码  收藏代码
  1. private final static String[] mContactsProjection = new String[] {  
  2.             ContactsContract.CommonDataKinds.Phone.CONTACT_ID,  
  3.             ContactsContract.CommonDataKinds.Phone.TYPE,  
  4.             ContactsContract.CommonDataKinds.Phone.NUMBER,  
  5.             ContactsContract.Contacts.DISPLAY_NAME,  
  6.             ContactsContract.Contacts.PHOTO_ID  
  7.     };  


下面对应改为 
Java代码  收藏代码
  1. while (phoneCursor.getPosition() != phoneCursor.getCount()) {  
  2.                 ContactEntity contactentity = new ContactEntity();  
  3.                 contactentity.contacts_id = phoneCursor.getLong(0);  
  4.                 contactentity.contacts_phone_type = phoneCursor.getInt(1);  
  5.                 contactentity.contacts_phone_number = phoneCursor.getString(2)  
  6.                         .replace("-""");  
  7.                 contactentity.contacts_display_name = phoneCursor.getString(3).replace("-""");  
  8.                 contactentity.contacts_photo_id = phoneCursor.getString(4);  
  9.                 // spell name can  
  10.                 contactentity.spellName = PinYin.getInstance(this)  
  11.                         .getPinyinString(contactentity.contacts_display_name);  
  12.   
  13.                 // Log.i(TAG, "contactentity.contact_id: " +  
  14.                 // contactentity.contact_id  
  15.                 // + " contactentity.contacts_phone_type: "  
  16.                 // + contactentity.contacts_phone_type  
  17.                 // + " contactentity.contacts_phone_number: "  
  18.                 // + contactentity.contacts_phone_number  
  19.                 // + "contactentity.contacts_display_name: "  
  20.                 // + contactentity.contacts_display_name  
  21.                 // + "contactentity.contact_phone_bmp: "  
  22.                 // + contactentity.contact_phone_bmp);  
  23.                 phoneCursor.moveToNext();  
  24.                 customArrayList.add(contactentity);  
  25.             }  
  26.         }  

这样改变后只读一次数据库! 
在1000联系人的情况下耗时打LOG得到不到2000毫秒! 
其他优化方向! 
1、查询数据库时把managedquerey第二参数projection写时!只查需要的列!不查询全部! 
2、在contactentity.contact_id = phoneCursor 
.getLong(phoneCursor 
.getColumnIndex(ContactsContract.CommonDataKinds.Phone.CONTACT_ID));取值时直接用数组序号0,1,2代替! 
3.图片等大数据量数据可放在getview方法中直接赋值而不通过对象传递!
分享到:  
Ubuntu的root帐号激活 | String.replaceAll() 正则表达式
  • 2011-01-26 17:21
  • 浏览 977
  • 评论(2)
  • 分类:移动开发
  • 相关推荐
评论
2 楼 yelinsen05 2011-11-23  
dwpcny 写道
这样还是慢了 有PhoneLookUp类 是经过高度优化的读取联系人类 楼主可以试试吧

你想说的是下面这个吧.. 但你没看懂我的方法..
读取Android系统的通讯录时一般会先读取联系人然后再读取其号码,嵌套循环读取。如果通讯录人数不多速度尚可,但是通讯录里有1-2百人恐怕就比较慢了,如果硬件再差点体验就更差了。可以使用

ContactsContract.CommonDataKinds.Phone.CONTENT_URI(对应contacts2.db的数据视图view_data_restricted)视图来读取避免嵌套读取,而对于PhoneLookup.CONTENT_FILTER_URI确不能直接使用,这里分享一下小技巧。
一、PhoneLookup.CONTENT_FILTER_URI的一般用法

Uri uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNumber));
resolver.query(uri, new String[]{PhoneLookup.DISPLAY_NAME,... 

    API见这里。如果直接如下使用PhoneLookup.CONTENT_FILTER_URI会报IllegalArgument Exception错


getContentResolver().query(PhoneLookup.CONTENT_FILTER_URI,...
二、 技巧用法
        Cursor c = getContentResolver().query(Uri.withAppendedPath(
                PhoneLookup.CONTENT_FILTER_URI, "*"), new String[] {
                PhoneLookup._ID,
                PhoneLookup.NUMBER,
                PhoneLookup.DISPLAY_NAME,
                PhoneLookup.TYPE, PhoneLookup.LABEL }, null, null, sortOrder); 

    关键是这个"*",这样就能取到所有的号码以及相关的联系人的姓名以及其他相关字段,比通过联系人再查找其号码要方便很多。
1 楼 dwpcny 2011-11-16  
这样还是慢了 有PhoneLookUp类 是经过高度优化的读取联系人类 楼主可以试试吧
原创粉丝点击