編寫(xiě):spencer198711 - 原文:http://developer.android.com/training/contacts-provider/retrieve-names.html
這一課展示了如何根據(jù)要搜索的字符串去匹配聯(lián)系人的數(shù)據(jù),從而得到聯(lián)系人列表,你可以使用以下方法去實(shí)現(xiàn):
匹配聯(lián)系人名字
通過(guò)搜索字符串來(lái)匹配聯(lián)系人名字的全部或者部分來(lái)獲得聯(lián)系人列表。因?yàn)镃ontacts Provider允許多個(gè)實(shí)例擁有相同的名字,所以這種方法能夠返回匹配的列表。
匹配特定的數(shù)據(jù)類(lèi)型,比如電話號(hào)碼
通過(guò)搜索字符串來(lái)匹配聯(lián)系人的某一特定數(shù)據(jù)類(lèi)型(如電子郵件地址),來(lái)取得符合要求的聯(lián)系人列表。例如,這種方法可以列出電子郵件地址與搜索字符相匹配的所有聯(lián)系人。
匹配任意類(lèi)型的數(shù)據(jù)
通過(guò)搜索字符串來(lái)匹配聯(lián)系人詳情的所有數(shù)據(jù)類(lèi)型,包括名字、電話號(hào)碼、地址、電子郵件地址等等。例如,這種方法接受任意數(shù)據(jù)類(lèi)型的搜索字符串,并列出與這個(gè)搜索字符串相匹配的聯(lián)系人。
Note:這一課的所有例子都使用CursorLoader獲取Contacts Provider中的數(shù)據(jù)。CursorLoader在一個(gè)與UI線程相獨(dú)立的工作線程進(jìn)行查詢(xún)操作。這保證了數(shù)據(jù)查詢(xún)不會(huì)降低UI響應(yīng)的時(shí)間,以免引起槽糕的用戶(hù)體驗(yàn)。更多信息,請(qǐng)參照在后臺(tái)加載數(shù)據(jù)。
為了能夠在Contacts Provider中做任意類(lèi)型的搜索,我們的應(yīng)用必須擁有READ_CONTACTS權(quán)限。為了擁有這個(gè)權(quán)限,我們需要在項(xiàng)目的manifest文件的<manifest>節(jié)點(diǎn)中添加
<uses-permission android:name="android.permission.READ_CONTACTS" />
這種方法根據(jù)搜索字符串,去匹配Contacts Provider的ContactsContract.Contacts表中的聯(lián)系人名字。通常希望在ListView中展示結(jié)果,去讓用戶(hù)在所有匹配的聯(lián)系人中做選擇。
為了能夠?qū)⑺阉鹘Y(jié)果展示在列表中,我們需要一個(gè)包含ListView以及其他布局控件的主布局文件,和一個(gè)定義列表中每一項(xiàng)的布局文件。例如,可以使用以下XML代碼去創(chuàng)建主布局文件res/layout/contacts_list_view.xml:
<?xml version="1.0" encoding="utf-8"?>
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
這個(gè)XML代碼使用了Android內(nèi)建的ListView控件,他的id是android:id/list。
使用以下XML代碼定義列表項(xiàng)布局文件contacts_list_item.xml:
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/text1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"/>
這個(gè)XML代碼使用了Android內(nèi)建的TextView控件,他的id是android:text1。
Note:本課并不會(huì)描述如何從用戶(hù)那里獲取搜索字符串的界面,因?yàn)槲覀兛赡軙?huì)間接地獲取這個(gè)字符串。比如說(shuō),我們可能會(huì)給用戶(hù)一個(gè)選項(xiàng)去輸入文字信息,把這些文字信息作為搜索字符串去匹配聯(lián)系人的名字。
剛剛寫(xiě)的這兩個(gè)布局文件定義了一個(gè)顯示ListView的用戶(hù)界面。下一步是編寫(xiě)使用這個(gè)用戶(hù)界面顯示聯(lián)系人列表的代碼。
為了顯示聯(lián)系人列表,需要定義一個(gè)由Activity加載的Fragment。使用Fragment是一個(gè)比較靈活的方法,因?yàn)槲覀兛梢允褂靡粋€(gè)Fragment去顯示列表,用另一個(gè)Fragment顯示用戶(hù)在列表中選擇的聯(lián)系人的詳情。使用這種方式,我們可以將本課程中展示的方法和另外一課獲取聯(lián)系人詳情的方法聯(lián)系起來(lái)。
想要學(xué)習(xí)如何在Activity中使用一個(gè)或者多個(gè)Fragment,請(qǐng)閱讀培訓(xùn)課程使用Fragment建立動(dòng)態(tài)UI。
為了方便我們編寫(xiě)對(duì)Contacts Provider的查詢(xún),Android框架提供了一個(gè)叫做ContactsContract的契約類(lèi),這個(gè)類(lèi)定義了一些對(duì)查詢(xún)Contacts Provider很有用的常量和方法。當(dāng)我們使用這個(gè)類(lèi)的時(shí)候,我們不用自己定義內(nèi)容URI、表名、列名等常量。使用這個(gè)類(lèi),只需要引入以下類(lèi)聲明:
import android.provider.ContactsContract;
由于代碼中使用了CursorLoader去獲取provider的數(shù)據(jù),所以我們必須實(shí)現(xiàn)加載器接口LoaderManager.LoaderCallbacks。同時(shí),為了檢測(cè)用戶(hù)從結(jié)果列表中選擇了哪一個(gè)聯(lián)系人,必須實(shí)現(xiàn)適配器接口AdapterView.OnItemClickListener。例如:
...
import android.support.v4.app.Fragment;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.widget.AdapterView;
...
public class ContactsFragment extends Fragment implements
LoaderManager.LoaderCallbacks<Cursor>,
AdapterView.OnItemClickListener {
定義在其他代部分碼中使用的全局變量:
...
/*
* Defines an array that contains column names to move from
* the Cursor to the ListView.
*/
@SuppressLint("InlinedApi")
private final static String[] FROM_COLUMNS = {
Build.VERSION.SDK_INT
>= Build.VERSION_CODES.HONEYCOMB ?
Contacts.DISPLAY_NAME_PRIMARY :
Contacts.DISPLAY_NAME
};
/*
* Defines an array that contains resource ids for the layout views
* that get the Cursor column contents. The id is pre-defined in
* the Android framework, so it is prefaced with "android.R.id"
*/
private final static int[] TO_IDS = {
android.R.id.text1
};
// Define global mutable variables
// Define a ListView object
ListView mContactsList;
// Define variables for the contact the user selects
// The contact's _ID value
long mContactId;
// The contact's LOOKUP_KEY
String mContactKey;
// A content URI for the selected contact
Uri mContactUri;
// An adapter that binds the result Cursor to the ListView
private SimpleCursorAdapter mCursorAdapter;
...
Note:由于Contacts.DISPLAY_NAME_PRIMARY需要在Android 3.0(API版本11)或者更高的版本才能使用,如果應(yīng)用的minSdkVersion是10或者更低,會(huì)在eclipse中產(chǎn)生警告信息。為了關(guān)閉這個(gè)警告,我們可以在FROM_COLUMNS定義之前加上@SuppressLint("InlinedApi")注解。
為了初始化Fragment,Android系統(tǒng)需要我們?yōu)檫@個(gè)Fragment添加空的、公有的構(gòu)造方法,同時(shí)在回調(diào)方法onCreateView()中綁定界面。例如:
// Empty public constructor, required by the system
public ContactsFragment() {}
// A UI Fragment must inflate its View
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the fragment layout
return inflater.inflate(R.layout.contact_list_fragment,
container, false);
}
設(shè)置SimpleCursorAdapter,將搜索結(jié)果綁定到ListView。為了獲得顯示聯(lián)系人列表的ListView控件,需要使用Fragment的父Activity調(diào)用Activity.findViewById()。當(dāng)調(diào)用setAdapter()的時(shí)候,需要使用父Activity的上下文(Context)。
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
...
// Gets the ListView from the View list of the parent activity
mContactsList =
(ListView) getActivity().findViewById(R.layout.contact_list_view);
// Gets a CursorAdapter
mCursorAdapter = new SimpleCursorAdapter(
getActivity(),
R.layout.contact_list_item,
null,
FROM_COLUMNS, TO_IDS,
0);
// Sets the adapter for the ListView
mContactsList.setAdapter(mCursorAdapter);
}
當(dāng)我們顯示搜索列表結(jié)果的時(shí)候,我們通常會(huì)讓用戶(hù)選擇某一個(gè)聯(lián)系人去做進(jìn)一步的處理。例如,當(dāng)用戶(hù)選擇某一個(gè)聯(lián)系人的時(shí)候,可以在地圖上顯示這個(gè)聯(lián)系人的地址。為了能夠提供這個(gè)功能,我們需要定義當(dāng)前的Fragment為一個(gè)點(diǎn)擊監(jiān)聽(tīng)器,這需要這個(gè)類(lèi)實(shí)現(xiàn)AdapterView.OnItemClickListener接口,就像前面介紹的定義顯示聯(lián)系人列表的Fragment那樣。
繼續(xù)設(shè)置這個(gè)監(jiān)聽(tīng)器,需要在onActivityCreated()方法中調(diào)用setOnItemClickListener()以使得這個(gè)監(jiān)聽(tīng)器綁定到ListView。例如:
public void onActivityCreated(Bundle savedInstanceState) {
...
// Set the item click listener to be the current fragment.
mContactsList.setOnItemClickListener(this);
...
}
由于指定了當(dāng)前的Fragment作為L(zhǎng)istView的點(diǎn)擊監(jiān)聽(tīng)器,現(xiàn)在我們需要實(shí)現(xiàn)處理點(diǎn)擊事件的onItemClick()方法。這個(gè)會(huì)在隨后討論。
定義一個(gè)常量,這個(gè)常量包含我們想要從查詢(xún)結(jié)果中返回的列。Listview中的每一項(xiàng)顯示了一個(gè)聯(lián)系人的名字。在Android 3.0(API version 11)或者更高的版本,這個(gè)列的名字是Contacts.DISPLAY_NAME_PRIMARY;在Android 3.0之前,這個(gè)列的名字是Contacts.DISPLAY_NAME。
在SimpleCursorAdapter綁定過(guò)程中會(huì)用到Contacts._ID列。 Contacts._ID和LOOKUP_KEY一同用來(lái)構(gòu)建用戶(hù)選擇的聯(lián)系人的內(nèi)容URI。
...
@SuppressLint("InlinedApi")
private static final String[] PROJECTION = {
Contacts._ID,
Contacts.LOOKUP_KEY,
Build.VERSION.SDK_INT
>= Build.VERSION_CODES.HONEYCOMB ?
Contacts.DISPLAY_NAME_PRIMARY :
Contacts.DISPLAY_NAME
};
為了從Cursor中獲得單獨(dú)某一列的數(shù)據(jù),我們需要知道這一列在Cursor中的索引值。我們需要定義Cursor列的索引值,這些索引值與我們定義查詢(xún)映射的列的順序是一樣的。例如:
// The column index for the _ID column
private static final int CONTACT_ID_INDEX = 0;
// The column index for the LOOKUP_KEY column
private static final int LOOKUP_KEY_INDEX = 1;
為了指定我們想要的數(shù)據(jù),我們需要?jiǎng)?chuàng)建一個(gè)包含文本表達(dá)式和變量的組合,去告訴provider我們需要的數(shù)據(jù)列和想要的值。
對(duì)于文本表達(dá)式,定義一個(gè)常量,列出所有搜索到的列。盡管這個(gè)表達(dá)式可以包含變量值,但是建議用"?"占位符來(lái)替代這個(gè)值。在搜索的時(shí)候,占位符里的值會(huì)被數(shù)組里的值所取代。使用"?"占位符確保了搜索條件是由綁定產(chǎn)生而不是由SQL編譯產(chǎn)生。這個(gè)方法消除了惡意SQL注入的可能。例如:
// Defines the text expression
@SuppressLint("InlinedApi")
private static final String SELECTION =
Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ?
Contacts.DISPLAY_NAME_PRIMARY + " LIKE ?" :
Contacts.DISPLAY_NAME + " LIKE ?";
// Defines a variable for the search string
private String mSearchString;
// Defines the array to hold values that replace the ?
private String[] mSelectionArgs = { mSearchString };
在之前的內(nèi)容中,我們?yōu)長(zhǎng)istview設(shè)置了列表項(xiàng)點(diǎn)擊監(jiān)聽(tīng)器,現(xiàn)在需要定義AdapterView.OnItemClickListener.onItemClick()方法以實(shí)現(xiàn)監(jiān)聽(tīng)器行為:
@Override
public void onItemClick(
AdapterView<?> parent, View item, int position, long rowID) {
// Get the Cursor
Cursor cursor = parent.getAdapter().getCursor();
// Move to the selected contact
cursor.moveToPosition(position);
// Get the _ID value
mContactId = getLong(CONTACT_ID_INDEX);
// Get the selected LOOKUP KEY
mContactKey = getString(CONTACT_KEY_INDEX);
// Create the contact's content Uri
mContactUri = Contacts.getLookupUri(mContactId, mContactKey);
/*
* You can use mContactUri as the content URI for retrieving
* the details for a contact.
*/
}
由于使用了CursorLoader獲取數(shù)據(jù),我們必須初始化后臺(tái)線程和其他的控制異步獲取數(shù)據(jù)的變量。需要在onActivityCreated()方法中做初始化的工作,這個(gè)方法是在Fragment的界面顯示之前被調(diào)用的,相關(guān)代碼展示如下:
public class ContactsFragment extends Fragment implements
LoaderManager.LoaderCallbacks<Cursor> {
...
// Called just before the Fragment displays its UI
@Override
public void onActivityCreated(Bundle savedInstanceState) {
// Always call the super method first
super.onActivityCreated(savedInstanceState);
...
// Initializes the loader
getLoaderManager().initLoader(0, null, this);
我們需要實(shí)現(xiàn)onCreateLoader()方法,這個(gè)方法是在調(diào)用initLoader()后馬上被loader框架調(diào)用的。
在onCreateLoader()方法中,設(shè)置搜索字符串模式。為了讓一個(gè)字符串符合一個(gè)模式,插入"%"字符代表0個(gè)或多個(gè)字符,插入"_"代表一個(gè)字符。例如,模式%Jefferson%將會(huì)匹配“Thomas Jefferson”和“Jefferson Davis”。
這個(gè)方法返回一個(gè)CursorLoader對(duì)象。對(duì)于內(nèi)容URI,則使用了Contacts.CONTENT_URI,這個(gè)URI關(guān)聯(lián)到整個(gè)表,例子如下所示:
...
@Override
public Loader<Cursor> onCreateLoader(int loaderId, Bundle args) {
/*
* Makes search string into pattern and
* stores it in the selection array
*/
mSelectionArgs[0] = "%" + mSearchString + "%";
// Starts the query
return new CursorLoader(
getActivity(),
Contacts.CONTENT_URI,
PROJECTION,
SELECTION,
mSelectionArgs,
null
);
}
實(shí)現(xiàn)onLoadFinished()方法。當(dāng)Contacts Provider返回查詢(xún)結(jié)果的時(shí)候,loader框架會(huì)調(diào)用onLoadFinished()方法。在這個(gè)方法中,將查詢(xún)結(jié)果Cursor傳給SimpleCursorAdapter,這將會(huì)使用這個(gè)搜索結(jié)果自動(dòng)更新ListView。
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
// Put the result Cursor in the adapter for the ListView
mCursorAdapter.swapCursor(cursor);
}
當(dāng)loader框架檢測(cè)到結(jié)果集Cursor包含過(guò)時(shí)的數(shù)據(jù)時(shí),它會(huì)調(diào)用onLoaderReset()。我們需要?jiǎng)h除SimpleCursorAdapter對(duì)已經(jīng)存在Cursor的引用。如果不這么做的話,loader框架將不會(huì)回收Cursor對(duì)象,這將會(huì)導(dǎo)致內(nèi)存泄漏。例如:
@Override
public void onLoaderReset(Loader<Cursor> loader) {
// Delete the reference to the existing Cursor
mCursorAdapter.swapCursor(null);
}
我們現(xiàn)在已經(jīng)實(shí)現(xiàn)了一個(gè)應(yīng)用的關(guān)鍵部分,即根據(jù)搜索字符串匹配聯(lián)系人名字和將獲得的結(jié)果展示在ListView中。用戶(hù)可以點(diǎn)擊選擇一個(gè)聯(lián)系人名字,這將會(huì)觸發(fā)一個(gè)監(jiān)聽(tīng)器,在監(jiān)聽(tīng)器的回調(diào)函數(shù)中,你可以使用此聯(lián)系人的數(shù)據(jù)做進(jìn)一步的處理。例如,你可以進(jìn)一步獲取此聯(lián)系人的詳情,想要知道何如獲取聯(lián)系人詳情,請(qǐng)繼續(xù)學(xué)習(xí)下一課獲取聯(lián)系人詳情。
想要了解更多搜索用戶(hù)界面的知識(shí),請(qǐng)參考API指南Creating a Search Interface。
這一課的以下內(nèi)容展示了在Contacts Provider中查找聯(lián)系人的其他方法。
這種方法可以讓我們指定想要匹配的數(shù)據(jù)類(lèi)型。根據(jù)名字去檢索是這種類(lèi)型的查詢(xún)的一個(gè)具體例子。但也可以用任何與聯(lián)系人詳情數(shù)據(jù)相關(guān)的數(shù)據(jù)類(lèi)型去做查詢(xún)。例如,我們可以檢索具有特定郵政編碼聯(lián)系人,在這種情況下,搜索字符串將會(huì)去匹配存儲(chǔ)在一個(gè)郵政編碼列中的數(shù)據(jù)。
為了實(shí)現(xiàn)這種類(lèi)型的檢索,首先實(shí)現(xiàn)以下的代碼,正如之前的內(nèi)容所展示的:
定義Cursor的列索引常量
盡管我們現(xiàn)在從不同的表中取數(shù)據(jù),檢索列的映射順序是一樣的,所以我們可以為這個(gè)Cursor使用同樣的索引常量。
為了將搜索字符串匹配特定的詳請(qǐng)數(shù)據(jù)類(lèi)型并顯示結(jié)果,以下的步驟展示了我們需要額外添加的代碼。
為了從特定類(lèi)型的詳請(qǐng)數(shù)據(jù)中查詢(xún),我們必須知道的數(shù)據(jù)類(lèi)型的自定義MIME類(lèi)型的值。每一個(gè)數(shù)據(jù)類(lèi)型擁有唯一的MIME
類(lèi)型值,這個(gè)值在ContactsContract.CommonDataKinds的子類(lèi)中被定義為常量CONTENT_ITEM_TYPE
,并且與實(shí)際的數(shù)據(jù)類(lèi)型相關(guān)。子類(lèi)的名字會(huì)表明它們的實(shí)際數(shù)據(jù)類(lèi)型。例如,email數(shù)據(jù)的子類(lèi)是ContactsContract.CommonDataKinds.Email
,并且email的自定義MIME類(lèi)型是Email.CONTENT_ITEM_TYPE
。
在搜索中需要使用ContactsContract.Data類(lèi)。同時(shí)所有需要的常量,包括數(shù)據(jù)映射、選擇字句、排序規(guī)則都是由這個(gè)類(lèi)定義或繼承自此類(lèi)。
為了定義一個(gè)查詢(xún)映射,請(qǐng)選擇一個(gè)或者多個(gè)定義在ContactsContract.Data表或其子類(lèi)的列。Contacts Provider在返回行結(jié)果集之前,隱式的連接了ContactsContract.Data表和其他表。例如:
@SuppressLint("InlinedApi")
private static final String[] PROJECTION = {
/*
* The detail data row ID. To make a ListView work,
* this column is required.
*/
Data._ID,
// The primary display name
Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ?
Data.DISPLAY_NAME_PRIMARY :
Data.DISPLAY_NAME,
// The contact's _ID, to construct a content URI
Data.CONTACT_ID
// The contact's LOOKUP_KEY, to construct a content URI
Data.LOOKUP_KEY (a permanent link to the contact
};
為了根據(jù)特定的聯(lián)系人數(shù)據(jù)類(lèi)型查詢(xún)字符串,請(qǐng)按照以下方法構(gòu)建查詢(xún)選擇子句:
CONTENT_ITEM_TYPE
常量。例如,email數(shù)據(jù)的MIME類(lèi)型值是Email.CONTENT_ITEM_TYPE
。需要在這個(gè)常量值的開(kāi)頭和結(jié)尾加上"'"(單引號(hào))。否則,provider會(huì)把這個(gè)值翻譯成一個(gè)變量而不是一個(gè)字符串。我們不需要為這個(gè)值提供占位符,因?yàn)槲覀冊(cè)谑褂靡粋€(gè)常量而不是用戶(hù)提供的值。例如:/*
* Constructs search criteria from the search string
* and email MIME type
*/
private static final String SELECTION =
/*
* Searches for an email address
* that matches the search string
*/
Email.ADDRESS + " LIKE ? " + "AND " +
/*
* Searches for a MIME type that matches
* the value of the constant
* Email.CONTENT_ITEM_TYPE. Note the
* single quotes surrounding Email.CONTENT_ITEM_TYPE.
*/
Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'";
下一步,定義包含選擇字符串的變量:
String mSearchString;
String[] mSelectionArgs = { "" };
現(xiàn)在,我們已經(jīng)詳述了想要的數(shù)據(jù)和如何找到這些數(shù)據(jù),如何在onCreateLoader()方法中定義一個(gè)查詢(xún)。使用你的數(shù)據(jù)映射、查詢(xún)選擇表達(dá)式和一個(gè)數(shù)組作為選擇表達(dá)式的參數(shù),并從這個(gè)方法中返回一個(gè)新的CursorLoader對(duì)象。而內(nèi)容URI需要使用Data.CONTENT_URI,例如:
@Override
public Loader<Cursor> onCreateLoader(int loaderId, Bundle args) {
// OPTIONAL: Makes search string into pattern
mSearchString = "%" + mSearchString + "%";
// Puts the search string into the selection criteria
mSelectionArgs[0] = mSearchString;
// Starts the query
return new CursorLoader(
getActivity(),
Data.CONTENT_URI,
PROJECTION,
SELECTION,
mSelectionArgs,
null
);
}
這段代碼片段是基于特定的聯(lián)系人詳情數(shù)據(jù)類(lèi)型的簡(jiǎn)單反向查找。如果我們的應(yīng)用關(guān)注于某一種特定的數(shù)據(jù)類(lèi)型,比如說(shuō)email地址,并且允許用戶(hù)獲得與此數(shù)據(jù)相關(guān)的聯(lián)系人名字,這種形式的查詢(xún)是最好的方法。
根據(jù)任意數(shù)據(jù)類(lèi)型獲取聯(lián)系人時(shí),如果聯(lián)系人的數(shù)據(jù)(這些數(shù)據(jù)包括名字、email地址、郵件地址和電話號(hào)碼等等)能匹配要搜索的字符串,那么該聯(lián)系人信息將會(huì)被返回。這種搜索結(jié)果會(huì)比較廣泛。例如,如果搜索字符串是"Doe",搜索任意類(lèi)型的數(shù)據(jù)將會(huì)返回名字為"Jone Doe"的聯(lián)系人,也會(huì)返回一個(gè)住在"Doe Street"的聯(lián)系人。
為了完成這種類(lèi)型的查詢(xún),就像之前展示的那樣,首先需要實(shí)現(xiàn)以下代碼:
定義Cursor的列索引常量
對(duì)于這種形式的查詢(xún),你需要使用與在“使用特定類(lèi)型的數(shù)據(jù)匹配聯(lián)系人”那一節(jié)中相同的表,也可以使用相同的列索引。
以下的步驟展示了為了能夠根據(jù)任意的數(shù)據(jù)類(lèi)型去匹配查詢(xún)字符串并顯示結(jié)果列表,我們需要添加的額外代碼。
不需要為mSelectionArgs定義查詢(xún)標(biāo)準(zhǔn)常量SELECTION。這些內(nèi)容在這種類(lèi)型的檢索不會(huì)被用到。
實(shí)現(xiàn)onCreateLoader()方法,返回一個(gè)新的CursorLoader對(duì)象。我們不需要把搜索字符串轉(zhuǎn)化成一個(gè)搜索模式,因?yàn)镃ontacts Provider會(huì)自動(dòng)做這件事。使用Contacts.CONTENT_FILTER_URI作為基礎(chǔ)查詢(xún)URI,并使用Uri.withAppendedPath()方法將搜索字符串添加到基礎(chǔ)URI中。使用這個(gè)URI會(huì)自動(dòng)觸發(fā)對(duì)任意數(shù)據(jù)類(lèi)型的搜索,就像以下例子所示:
@Override
public Loader<Cursor> onCreateLoader(int loaderId, Bundle args) {
/*
* Appends the search string to the base URI. Always
* encode search strings to ensure they're in proper
* format.
*/
Uri contentUri = Uri.withAppendedPath(
Contacts.CONTENT_FILTER_URI,
Uri.encode(mSearchString));
// Starts the query
return new CursorLoader(
getActivity(),
contentUri,
PROJECTION,
null,
null,
null
);
}
這段代碼片段,是想要在Contacts Provider中建立廣泛搜索類(lèi)型應(yīng)用的基礎(chǔ)部分。這種方法對(duì)那些想要實(shí)現(xiàn)與通訊錄應(yīng)用聯(lián)系人列表中相似搜索功能的應(yīng)用,會(huì)很有幫助。