Android中的聯繫人都保存在一個SQLite數據庫中,有興趣的可以使用adb直接push出來看一下里面的表和視圖的結構,
它的路徑爲:/data/data/com.android.providers.contacts/databases/contacts2.db
在聯繫人數據庫中,保存的都是一些小的數據表,即與把所有數據保存成一個表不同,它會對聯繫人的資料模塊化,然後分成多個表保存。
表與表之間使用id相關聯起來,這樣做的目的是儘量減小數據表的規模,提高數據檢索的速度,因爲我們檢索的時候不是每次都需要讀取所有的聯繫人資料的,這樣可以更靈活的選擇我們所關心的內容,提高檢索速度,
雖然分開的保存數據,可以提高檢索的速度,但是也給我們帶來了一些不便,就是需要把這些分開的表再重新聯合起來,組成我們所需要的完整的數據。好在這些,android已經替我們準備好了,它在數據庫裏面建了一些視圖,呵呵,視圖就是虛擬表。並且,android也提供了很多接口,通過ContentResolver().query方法,傳入不同的URI即可訪問相應的數據集。
在聯繫人數據庫裏面聯繫人和電話號碼是分別存在兩個表裏面的,因爲存在一個聯繫人擁有幾個號碼的情況,所以android爲聯繫人和手機號碼分別單獨創建了相應的視圖。
聯繫人信息的視圖裏面只保存與聯繫人相關的資料,例如姓名,是否有手機號碼等。
而手機號碼資料則是每一個電話號碼爲一條記錄,如果有一個聯繫人有3個號碼,則裏面會出現3個該聯繫人的記錄,號碼分別爲他的三個號碼。
如果是需要讀取聯繫人信息,傳入的URI爲:ContactsContract.Contacts.CONTENT_URI
如果是需要讀取手機號碼信息傳入的URI爲:ContactsContract.CommonDataKinds.Phone.CONTENT_URI
下面再看看query函數的原型,只讀取關心的字段,應該可以提高一點速度
query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)
projection:是需要讀取的字段
selection:是數據檢索的條件
selectionArgs:是數據檢索條件的參數
sortOrder:是排序的字段
在android聯繫人表裏面一個兩個比較有意思的字體sort_key和sort_key_alt,它裏面保存的是聯繫人名字的拼音字母,
例如聯繫人名字是“李明”,則sort_key保存的是“LI李MING明”,這樣如果是按sort_key或sort_key_alt排序的話,就可以實現按漢字的拼音字母排序了,,,
下面給讀取系統所有聯繫人的代碼片段,讀取所有的聯繫人,然後每讀一個聯繫人,再把該聯繫人的所有號碼讀出來
(這個因爲需要不斷的去檢索數據庫,所以會很慢,大家有什麼方法提高SQLite數據庫的檢索的方法沒??):
// the selected cols for contact users
String[] selectCol = new String[]{
ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.Contacts.HAS_PHONE_NUMBER,
ContactsContract.Contacts._ID
};
public static final int COL_NAME = 0;
public static final int COL_HAS_PHONE = 1;
public static final int COL_ID = 2;
// the selected cols for phones of a user
String[] selPhoneCols = new String[] {
ContactsContract.CommonDataKinds.Phone.NUMBER,
ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Phone.TYPE
};
public static final int COL_PHONE_NUMBER = 0;
public static final int COL_PHONE_NAME = 1;
public static final int COL_PHONE_TYPE = 2;
public void getContactList() {
String select = "((" + Contacts.DISPLAY_NAME + " NOTNULL) AND ("
+ Contacts.HAS_PHONE_NUMBER + "=1) AND ("
+ Contacts.DISPLAY_NAME + " != '' ))";
list = new ArrayList<ContactItemData>();
Cursor cursor = this.getContentResolver().query(
ContactsContract.Contacts.CONTENT_URI, selectCol, select, null,
ContactsContract.Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC");
if (cursor ==null) {
Toast.makeText(this, "cursor is null!", Toast.LENGTH_LONG).show();
return;
}
if (cursor.getCount() == 0) {
Toast.makeText(this, "cursor count is zero!", Toast.LENGTH_LONG).show();
return;
}
cursor.moveToFirst();
while(!cursor.isAfterLast()) {
int contactId;
contactId = cursor.getInt(cursor.getColumnIndex(
ContactsContract.Contacts._ID));
if (cursor.getInt(COL_HAS_PHONE)>0) {
// the contact has numbers
// 獲得聯繫人的電話號碼列表
String displayName;
displayName = cursor.getString(COL_NAME);
Cursor phoneCursor = getContentResolver().query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
selPhoneCols,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID
+ "=" + contactId, null, null);
if(phoneCursor.moveToFirst()) {
do
{
//遍歷所有的聯繫人下面所有的電話號碼
String phoneNumber = phoneCursor.getString(COL_PHONE_NUMBER);
ContactItemData data = new ContactItemData();
String phoneFiled = new String();
data.name = displayName;
data.number = phoneFiled + ":" + phoneNumber;
data.check = false;
list.add(data);
}while(phoneCursor.moveToNext());
}
}
cursor.moveToNext();
}
}
讀取所有號碼的片段:
/**
* Yao.GUET
* Blog: http://blog.csdn.net/Yao_GUET
*/
// the selected cols for phones numbers
String[] selPhoneCols = new String[] {
ContactsContract.CommonDataKinds.Phone.NUMBER,
ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Phone.TYPE,
ContactsContract.CommonDataKinds.Phone.LABEL,
ContactsContract.CommonDataKinds.Phone._ID
};
public static final int COL_PHONE_NUMBER = 0;
public static final int COL_PHONE_NAME = 1;
public static final int COL_PHONE_TYPE = 2;
public static final int COL_PHONE_LABEL = 3;
public ContactsCursorAdapter getContactCursorList() {
String select = "((" + Contacts.DISPLAY_NAME + " NOTNULL) AND ("
+ Contacts.DISPLAY_NAME + " != '' ) AND ("
+ ContactsContract.CommonDataKinds.Phone.NUMBER + " NOTNULL) AND ("
+ ContactsContract.CommonDataKinds.Phone.NUMBER + " != ''))";
Cursor cursor = this.getContentResolver().query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
selPhoneCols, select, null,
"sort_key_alt"
);
ContactsCursorAdapter adapter = new ContactsCursorAdapter(this,
R.layout.contact_item, cursor);
return adapter;
}