W3Cschool
恭喜您成為首批注冊(cè)用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
編寫:spencer198711 - 原文:http://developer.android.com/training/contacts-provider/retrieve-details.html
這一課展示了如何取得一個(gè)聯(lián)系人的詳細(xì)信息,比如email地址、電話號(hào)碼等。當(dāng)使用者去獲取聯(lián)系人信息的時(shí)候,這些信息正是他們所查找的。我們可以給他們關(guān)于一個(gè)聯(lián)系人的所有信息,或者僅僅顯示一個(gè)特定的數(shù)據(jù)類型,比如email地址。
這一課假設(shè)你已經(jīng)獲取到了一個(gè)用戶所選取的聯(lián)系人的ContactsContract.Contacts數(shù)據(jù)項(xiàng)。在獲取聯(lián)系人名字那一課展示了如何獲取聯(lián)系人列表。
為了取得一個(gè)聯(lián)系人的所有詳情,查找ContactsContract.Data表中包含聯(lián)系人LOOKUP_KEY列的任意行。因?yàn)镃ontacts Provider隱式地連接了ContactsContract.Contacts表和ContactsContract.Data表,所以這個(gè)LOOKUP_KEY列在ContactsContract.Data表中是可用的。關(guān)于LOOKUP_KEY列,在獲取聯(lián)系人名字那一課有詳細(xì)的描述。
Note:檢索一個(gè)聯(lián)系人的所有信息會(huì)降低設(shè)備的性能,因?yàn)檫@需要檢索ContactsContract.Data表的所有列。在使用這種方法之前,請(qǐng)認(rèn)真考慮對(duì)性能影響。
為了能夠讀Contacts Provider,我們的應(yīng)用必須擁有READ_CONTACTS權(quán)限。為了請(qǐng)求這個(gè)權(quán)限,需要在manifest文件的中添加如下子節(jié)點(diǎn):
<uses-permission android:name="android.permission.READ_CONTACTS" />
根據(jù)一行數(shù)據(jù)的數(shù)據(jù)類型,它可能會(huì)使用很多列或者只使用幾列。另外,數(shù)據(jù)會(huì)根據(jù)不同的數(shù)據(jù)類型而出現(xiàn)在不同的列中。為了確保能夠獲取所有數(shù)據(jù)類型的所有可能的數(shù)據(jù)列,需要在查詢映射中添加所有列的名字。如果要把Cursor綁定到ListView,記得要獲取Data._ID,否則的話,界面綁定就不會(huì)起作用。同時(shí)也需要獲取Data.MIMETYPE列,這樣才能識(shí)別我們獲取到的每一行數(shù)據(jù)的數(shù)據(jù)類型。例如:
private static final String PROJECTION =
{
Data._ID,
Data.MIMETYPE,
Data.DATA1,
Data.DATA2,
Data.DATA3,
Data.DATA4,
Data.DATA5,
Data.DATA6,
Data.DATA7,
Data.DATA8,
Data.DATA9,
Data.DATA10,
Data.DATA11,
Data.DATA12,
Data.DATA13,
Data.DATA14,
Data.DATA15
};
這個(gè)查詢映射使用了ContactsContract.Data類中定義的列名字,去獲取ContactsContract.Data表中一行的所有數(shù)據(jù)列。
我們也可以使用由ContactsContract.Data或其子類定義的列常量去設(shè)置查詢映射。需要注意的是,從SYNC1到SYNC4的數(shù)據(jù)列是sync adapter同步數(shù)據(jù)所使用的,它們的值對(duì)我們沒有意義。
為查詢選擇子句定義一個(gè)常量,一個(gè)包含查詢選擇參數(shù)的數(shù)組,以及一個(gè)保存查詢選擇值的變量。使用Contacts.LOOKUP_KEY列去查找這個(gè)聯(lián)系人。例如:
// Defines the selection clause
private static final String SELECTION = Data.LOOKUP_KEY + " = ?";
// Defines the array to hold the search criteria
private String[] mSelectionArgs = { "" };
/*
* Defines a variable to contain the selection value. Once you
* have the Cursor from the Contacts table, and you've selected
* the desired row, move the row's LOOKUP_KEY value into this
* variable.
*/
private String mLookupKey;
在查詢選擇表達(dá)式中使用 “?”占位符,確保了搜索是由綁定生成而不是由SQL編譯生成。這種方法消除了惡意SQL注入的可能性。
定義在查詢結(jié)果Cursor中希望的排序順序。按照Data.MIMETYPE去排序,可以讓特定數(shù)據(jù)類型的所有行排列在一起。這種形式的查詢排序參數(shù)讓所有具有email的行排在一起,讓所有具有電話的行排在一起……例如:
/*
* Defines a string that specifies a sort order of MIME type
*/
private static final String SORT_ORDER = Data.MIMETYPE;
Note:一些數(shù)據(jù)類型不使用子類型,所以不能按照子類型來排序。作為替代方法,我們不得不遍歷返回的Cursor,去判定當(dāng)前行的數(shù)據(jù)類型,為那些使用子類型的數(shù)據(jù)行保存數(shù)據(jù)。當(dāng)讀取完cursor后,我們可以根據(jù)子類型去排序每一個(gè)數(shù)據(jù)類型并顯示結(jié)果。
永遠(yuǎn)在后臺(tái)線程中去檢索Contacts Provider(或者其他content provider)的數(shù)據(jù)。使用Loader框架中的LoaderManager類和LoaderManager.LoaderCallbacks在后臺(tái)去做獲取數(shù)據(jù)的工作。
當(dāng)我們已經(jīng)準(zhǔn)備好去獲取數(shù)據(jù)行,需要通過調(diào)用initLoader()方法去初始化loader框架。傳遞一個(gè)Integer類型的標(biāo)識(shí)符給initLoader()方法,這個(gè)標(biāo)識(shí)符會(huì)傳遞給LoaderManager.LoaderCallbacks方法。當(dāng)在一個(gè)應(yīng)用中使用多個(gè)loader時(shí),這個(gè)標(biāo)識(shí)符能夠幫助我們區(qū)分它們。
以下的代碼片段展示了如何初始化loader框架:
public class DetailsFragment extends Fragment implements
LoaderManager.LoaderCallbacks<Cursor> {
...
// Defines a constant that identifies the loader
DETAILS_QUERY_ID = 0;
...
/*
* Invoked when the parent Activity is instantiated
* and the Fragment's UI is ready. Put final initialization
* steps here.
*/
@Override
onActivityCreated(Bundle savedInstanceState) {
...
// Initializes the loader framework
getLoaderManager().initLoader(DETAILS_QUERY_ID, null, this);
實(shí)現(xiàn)onCreateLoader()方法。loader框架會(huì)在我們調(diào)用initLoader()方法后立即調(diào)用onCreateLoader()方法。這個(gè)方法會(huì)返回一個(gè)CursorLoader對(duì)象。由于搜索的是ContactsContract.Data表,所以需要使用常量Data.CONTENT_URI作為內(nèi)容URI。例如:
@Override
public Loader<Cursor> onCreateLoader(int loaderId, Bundle args) {
// Choose the proper action
switch (loaderId) {
case DETAILS_QUERY_ID:
// Assigns the selection parameter
mSelectionArgs[0] = mLookupKey;
// Starts the query
CursorLoader mLoader =
new CursorLoader(
getActivity(),
Data.CONTENT_URI,
PROJECTION,
SELECTION,
mSelectionArgs,
SORT_ORDER
);
...
}
實(shí)現(xiàn)onLoadFinished()方法。當(dāng)Contacts Provider返回查詢結(jié)果的時(shí)候,loader框架會(huì)調(diào)用onLoadFinished()方法。例如:
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
switch (loader.getId()) {
case DETAILS_QUERY_ID:
/*
* Process the resulting Cursor here.
*/
}
break;
...
}
}
當(dāng)loader框架檢測(cè)到結(jié)果集Cursor所對(duì)應(yīng)的數(shù)據(jù)已經(jīng)發(fā)生變化的時(shí)候,會(huì)調(diào)用onLoaderReset()方法。這時(shí),需要通過把Cursor設(shè)置為null來移除對(duì)已經(jīng)存在Cursor對(duì)象的引用。否則,loader框架就不會(huì)銷毀舊的Cursor對(duì)象,從而導(dǎo)致內(nèi)存泄漏。例如:
@Override
public void onLoaderReset(Loader<Cursor> loader) {
switch (loader.getId()) {
case DETAILS_QUERY_ID:
/*
* If you have current references to the Cursor,
* remove them here.
*/
}
break;
}
獲取聯(lián)系人的特定類型的信息,例如所有的email信息,跟獲取聯(lián)系人的所有詳細(xì)信息類似。下面的內(nèi)容是在獲取聯(lián)系人的所有詳細(xì)信息列出的代碼的基礎(chǔ)上作出的修改:
查詢映射
修改查詢映射使得能夠針對(duì)特定的數(shù)據(jù)類型去獲取列。同時(shí)需要修改查詢映射,來把在ContactsContract.CommonDataKinds子類中定義的列常量與數(shù)據(jù)類型對(duì)應(yīng)起來。
查詢選擇
修改查詢選擇子句去搜索特定類型的MIMETYPE值。
排序順序
由于僅僅搜索一種類型的詳細(xì)數(shù)據(jù),所以不需要將返回的Cursor按照Data.MIMETYPE進(jìn)行分組。
這些修改將會(huì)在下面的小節(jié)中詳細(xì)描述。
使用ContactsContract.CommonDataKinds的特定類型子類所定義的列名稱常量,定義我們想要獲取的數(shù)據(jù)列。如果我們打算把Cursor綁定到ListView,確保要獲取_ID
列。例如,為了獲取email數(shù)據(jù),需要定義以下數(shù)據(jù)映射:
private static final String[] PROJECTION =
{
Email._ID,
Email.ADDRESS,
Email.TYPE,
Email.LABEL
};
需要注意的是,這個(gè)查詢映射使用在ContactsContract.CommonDataKinds.Email類中定義的列名稱,來替代ContactsContract.Data類中定義的列名稱。使用email類型的列名稱使得代碼更具可讀性。
在查詢映射中,我們也可以使用ContactsContract.CommonDataKinds子類所定義的其他數(shù)據(jù)列。
根據(jù)我們想要找的特定聯(lián)系人的LOOKUP_KEY和聯(lián)系人詳細(xì)信息的Data.MIMETYPE定義一個(gè)搜索表達(dá)式,去獲取數(shù)據(jù)。把MIMETYPE的值從頭到尾用單引號(hào)括住,否則的話,content provider將會(huì)把這個(gè)常量當(dāng)成變量名而不是字符串。因?yàn)槲覀兪褂玫氖浅A?,而不是用戶提供的值,所以這里不需要使用占位符。例如:
/*
* Defines the selection clause. Search for a lookup key
* and the Email MIME type
*/
private static final String SELECTION =
Data.LOOKUP_KEY + " = ?" +
" AND " +
Data.MIMETYPE + " = " +
"'" + Email.CONTENT_ITEM_TYPE + "'";
// Defines the array to hold the search criteria
private String[] mSelectionArgs = { "" };
為查詢返回的Cursor定義一個(gè)排序規(guī)則。由于是檢索特定的數(shù)據(jù)類型,刪除根據(jù)MIMETYPE來排序的部分。而如果查詢的詳細(xì)數(shù)據(jù)類型包含子類型,可以根據(jù)這個(gè)子類型去排序。例如,對(duì)于email數(shù)據(jù),我們可以根據(jù)Email.TYPE排序:
private static final String SORT_ORDER = Email.TYPE + " ASC ";
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: