关于android通讯录加载大数据的优化问题
在最近的开发中,遇到一个问题,在自己开发的通讯录中,500条联系人加载时慢的问题。
最初把同步本地通讯录的操作,放在软件的loading页去做,把联系人读到缓存中,发现当数据大时,loading页会进入得很慢。然后试着用CursorAdapter去做,实现列表滚动去读数据库,但又发现当用户平凡刷列表时,会出现内存溢出的情况。
那怎么办呢,于是我综合两种情况的优点,进行了合并。当用户在滑动列表时,会把列表显示的部分通过读数据。读出来的数据放入一个MAP中,那么当用户下一次滑到之前的位置时,只需要从MAP中读取数据了。这样即解决了数据量大量,加载到缓存慢,又解决了滑动列表卡的问题。下面是代码
1.首先通过android通讯录数据库提供的索引表ContactsContract.RawContacts.CONTENT_URI把所有的联系人ID查询出来。
private List<Long> loadAllContactIds(){ List<Long> arr = new ArrayList<Long>(); Cursor cursor = cr.query(ContactsContract.RawContacts.CONTENT_URI, null, ContactsContract.RawContacts.DELETED + " = 0",null,null); if(null != cursor && cursor.moveToFirst()){ do{ long id = cursor.getLong(cursor.getColumnIndex(ContactsContract.RawContacts.CONTACT_ID)); arr.add(id); }while(cursor.moveToNext()); cursor.close(); } return arr; }
2.再通过ID把联系人的各种信息读出来。
private String loadAllContactInfo(long id){ Cursor cursor = cr.query(ContactsContract.Data.CONTENT_URI, null, ContactsContract.Data.RAW_CONTACT_ID + " = "+id,null,null); StringBuffer sb = new StringBuffer(); if(null != cursor && cursor.moveToFirst()){ do{ String type = cursor.getString(cursor.getColumnIndex(ContactsContract.Data.MIMETYPE)); if(type.equals(StructuredName.CONTENT_ITEM_TYPE)){ sb.append(cursor.getString(cursor.getColumnIndex(StructuredName.DISPLAY_NAME))).append("|"); }else if(type.equals(Nickname.CONTENT_ITEM_TYPE)){ sb.append(cursor.getString(cursor.getColumnIndex(Nickname.NAME))).append("|"); }else if(type.equals(Phone.CONTENT_ITEM_TYPE)){ sb.append(cursor.getString(cursor.getColumnIndex(Phone.NUMBER))).append("|"); }else if(type.equals(Event.CONTENT_ITEM_TYPE) && Event.TYPE.equals(Event.TYPE_BIRTHDAY)){ sb.append(cursor.getString(cursor.getColumnIndex(Event.DATA1))).append("|"); } }while(cursor.moveToNext()); cursor.close(); } return sb.toString(); }
3.自定义的adapter,
private class MyAdapter extends BaseAdapter{ private List<Long> ids; private Map<Long,String> maps; public MyAdapter(List<Long> ids){ this.ids = ids; maps = new HashMap<Long, String>(); } @Override public int getCount() { return this.ids.size(); } @Override public Object getItem(int position) { return this.ids.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { if(null == convertView){ convertView = LayoutInflater.from(TextTextActivity.this).inflate(android.R.layout.simple_list_item_1, null); } long id = ids.get(position); if(convertView instanceof TextView){ String res = maps.get(id); TextView tv = (TextView)convertView; if(TextUtils.isEmpty(res)){ res = loadAllContactInfo(id); maps.put(id, res); } tv.setText(res); } return convertView; } }