注:本文翻譯自Google官方的Android Developers Training文檔,譯者技術(shù)一般,由于喜愛(ài)安卓而產(chǎn)生了翻譯的念頭,純屬個(gè)人興趣愛(ài)好。
原文鏈接: http://developer.android.com/training/contacts-provider/retrieve-details.html
這節(jié)課將會(huì)展示如何獲取一個(gè)聯(lián)系人的詳細(xì)數(shù)據(jù),比如電子郵件地址,電話號(hào)碼,等等。當(dāng)用戶獲得一個(gè)聯(lián)系人后,他會(huì)想要查看他的詳細(xì)信息。你可以展示給他們所有的信息,或者只展示某一特定類型的信息,比如電子郵件地址。
這節(jié)課中,我們假設(shè)你已經(jīng)有了用戶選擇的一行 ContactsContract.Contacts 聯(lián)系人數(shù)據(jù)。在上一節(jié)課中(博客鏈接: http://www.cnblogs.com/jdneo/p/3674830.html )我們已經(jīng)講解了如何獲取聯(lián)系人列表的知識(shí)。
一). 獲取一個(gè)聯(lián)系人的詳細(xì)信息
要獲得一個(gè)聯(lián)系人的所有信息,需要搜索 ContactsContract.Data 表的每一行,看是否包含有聯(lián)系人的 LOOKUP_KEY 。這一列可在 ContactsContract.Data 中獲得,因?yàn)镃ontacts Provider在 ContactsContract.Contacts 表和 ContactsContract.Data 表之間執(zhí)行了一個(gè)隱式的連接。列 LOOKUP_KEY 的詳細(xì)信息在上一節(jié)課中 (博客鏈接: http://www.cnblogs.com/jdneo/p/3674830.html ) 已經(jīng)講授過(guò)了。
Note:
獲取某一個(gè)聯(lián)系人的所有信息會(huì)降低設(shè)備的性能,因?yàn)樗枰@取 ContactsContract.Data 表中所有列的數(shù)據(jù)。在你使用這一方法前要考慮到它對(duì)性能的影響。
請(qǐng)求權(quán)限
要從Contacts Provider中讀取數(shù)據(jù),你的應(yīng)用必須具有 READ_CONTACTS 權(quán)限。要請(qǐng)求這一權(quán)限,在清單文件的 <manifest> 標(biāo)簽中添加如下子標(biāo)簽:
<
uses-permission
android:name
="android.permission.READ_CONTACTS"
/>
配置一個(gè)投影
根據(jù)每一行所包含的的數(shù)據(jù)類型,它可能使用一些列或很多列。另外,數(shù)據(jù)類型的不同會(huì)導(dǎo)致數(shù)據(jù)再不同的列中。要保證你能獲得對(duì)于所有可能數(shù)據(jù)類型所對(duì)應(yīng)的所有可能的列,你需要添加所有的列名到你的投影中。同時(shí),如果要把結(jié)果 Cursor 和一個(gè) ListView 綁定起來(lái),要獲取 Data._ID ;否則,綁定不會(huì)產(chǎn)生效果。同時(shí)要獲取 Data.MIMETYPE 這樣你就可以標(biāo)示出你獲得的每一行數(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
};
這一投影會(huì)為 ContactsContract.Data 表的一行獲取所有的列,使用在 ContactsContract.Data 類中所定義的列名。
或者,你也可以是用在 ContactsContract.Data 類中定義或者從它繼承的其它列常量。注意,列 SYNC1 到列 SYNC4 是被同步適配器使用的,所以他們的數(shù)據(jù)對(duì)我們現(xiàn)在的應(yīng)用場(chǎng)景而言沒(méi)有用。
定義選擇標(biāo)準(zhǔn)
為你的選擇語(yǔ)句定義一個(gè)常量,它是一個(gè)保存選擇語(yǔ)句的數(shù)組,以及一個(gè)保存對(duì)應(yīng)值的變量。使用 Contacts.LOOKUP_KEY 列來(lái)尋找聯(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;
在你的選擇語(yǔ)句中使用“?”作為占位符,能保證搜索語(yǔ)句是由綁定生成的而不是編譯生成的。這可以防止惡意的SQL注入攻擊。
定義排列順序
為結(jié)果 Cursor 定義你期望的排列順序。要讓某一類型數(shù)據(jù)的所有行根據(jù) Data.MIMETYPE 來(lái)排列。這一語(yǔ)句會(huì)讓所有email的行放在一起,所有電話號(hào)碼的行放在一起,等等。例如:
/*
* Defines a string that specifies a sort order of MIME type
*/
private
static
final
String SORT_ORDER = Data.MIMETYPE;
Note:
一些數(shù)據(jù)類型不使用子類,所以你不能用子類型來(lái)排序。相反的,你需要再返回的 Cursor 中進(jìn)行迭代,確定當(dāng)前行的數(shù)據(jù)類型,然后將使用子類型的行的數(shù)據(jù)保存起來(lái)。當(dāng)你完成讀cursor后,之后你就可以通過(guò)子類型排序并顯示結(jié)果。
初始化加載器
通常,我們?cè)诤笈_(tái)線程從Contacts Provider(以及其它所有的內(nèi)容提供器)獲取數(shù)據(jù)。使用由 LoaderManager 類,以及 LoaderManager.LoaderCallbacks 接口所定義的加載器框架來(lái)執(zhí)行后臺(tái)的獲取操作。
當(dāng)你準(zhǔn)備好獲取行后,通過(guò)調(diào)用 initLoader() 初始化加載器框架。將一個(gè)整形標(biāo)識(shí)傳遞給該方法;這一標(biāo)志會(huì)傳遞給 LoaderManager.LoaderCallbacks 方法。它可以幫助你區(qū)分這些加載器,從而在一個(gè)應(yīng)用中使用多個(gè)加載器。
下面的代碼樣例展示了如何初始化這個(gè)加載器框架:
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()
實(shí)現(xiàn) onCreateLoader() 方法,它會(huì)在你調(diào)用了 initLoader() 后被加載器框架調(diào)用。該方法返回一個(gè) CursorLoader 。因?yàn)槟阍谒阉? 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()和onLoaderReset()
實(shí)現(xiàn) onLoadFinished() 方法。當(dāng)Contacts Provider將查詢結(jié)果返回后,加載器框架會(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)加載器檢測(cè)到結(jié)果中的數(shù)據(jù)發(fā)生了變化,那么 onLoaderReset() 方法會(huì)被調(diào)用,此時(shí),將所有存在的 Cursor 引用設(shè)置成null來(lái)移除它們。如果你不這么做,加載器框架不會(huì)銷毀老的 Cursor ,這樣會(huì)導(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
;
}
二). 獲取一個(gè)聯(lián)系人的特定數(shù)據(jù)
要獲取一個(gè)聯(lián)系人的特定數(shù)據(jù),比如email,和檢索所有的詳細(xì)數(shù)據(jù)類似,你需要做的改變僅僅是實(shí)現(xiàn)課程 Retrieve All Details for a Contact (博客鏈接: http://www.cnblogs.com/jdneo/p/3674830.html ) 中列出的代碼:
投影
修改你的投影,使得列對(duì)應(yīng)于特定的要搜索的數(shù)據(jù)類型。同時(shí)修改投影,使用在 ContactsContract.CommonDataKinds 子類中對(duì)應(yīng)于數(shù)據(jù)類型的列常量名。
選擇
修改選擇語(yǔ)句,搜索對(duì)應(yīng)于你的數(shù)據(jù)類型的 MIMETYPE 值。
排列順序
因?yàn)槟阒凳褂脝我坏脑敿?xì)數(shù)據(jù)類型,所以不需要根據(jù) Data.MIMETYPE 將返回的 Cursor 分類。
這些修改在下列章節(jié)中描述。
定義一個(gè)投影
定義你要獲取的列,使用 ContactsContract.CommonDataKinds 子類中對(duì)應(yīng)于數(shù)據(jù)類型的列常量名。如果你想要將 Cursor 綁定到一個(gè) ListView 上,要確保獲取“ _ID ”列。例如,要獲取email數(shù)據(jù),定義下列投影:
private
static
final
String[] PROJECTION =
{
Email._ID,
Email.ADDRESS,
Email.TYPE,
Email.LABEL
};
注意這一投影使用 ContactsContract.CommonDataKinds.Email 類中定義的列名,而不是在類 ContactsContract.Data 中定義的列名。使用email的特定列名可以增加代碼的可讀性。
在投影中,你也可以使用在 ContactsContract.CommonDataKinds 子類中定義的其它列。
定義選擇標(biāo)準(zhǔn)
定義一個(gè)搜索表達(dá)式,它獲取你想要的特定聯(lián)系人的 LOOKUP_KEY 和 Data.MIMETYPE 行數(shù)據(jù)。對(duì)于 MIMETYPE 的值對(duì)應(yīng)的常量,用單引號(hào)(')將它括起來(lái);否則,提供器會(huì)把常量認(rèn)為是一個(gè)變量名而不是一個(gè)字符串值。你不需要為它使用一個(gè)占位符,因?yàn)槟闶褂玫氖且粋€(gè)常量而不是一個(gè)用戶提供的值。例如:
/*
* 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è)排列順序。因?yàn)槟惬@得的是一個(gè)特定的數(shù)據(jù)類型,所以略過(guò)對(duì) MIMETYPE 排序。另外,如果你正在搜索的詳細(xì)數(shù)據(jù)包含有一個(gè)子類型,可以對(duì)他排序。例如,對(duì)于Email數(shù)據(jù)你可以根據(jù) Email.TYPE 來(lái)排序:
private
static
final
String SORT_ORDER = Email.TYPE + " ASC ";
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061
微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元

