本課程將說明如何擷取資料與部分或部分聯絡人相符的聯絡人名單 搜尋字串,並採用以下技術:
- 比對聯絡人名稱
- 將搜尋字串與聯絡人名稱資料的全部或部分比對,擷取聯絡人清單。聯絡人提供者允許多個同名例項,因此這項技巧可傳回符合條件的清單。
- 比對特定類型的資料,例如電話號碼
- 將搜尋字串對應至特定類型的詳細資料,從而擷取聯絡人清單 像是電子郵件地址等資料舉例來說,這項技巧可用來列出 其電子郵件地址與搜尋字串相符的聯絡人。
- 符合任何類型的資料
- 將搜尋字串與任何類型的詳細資料 (包括姓名、電話號碼、街道地址、電子郵件地址等) 比對,擷取聯絡人清單。例如: 這項技巧可讓您接受任何類型的資料做為搜尋字串,然後將 與字串相符的聯絡人。
注意:本課程的所有範例都會使用 CursorLoader
從聯絡人供應器擷取資料。CursorLoader
會在與 UI 執行緒分開的執行緒上執行查詢。這麼做可確保查詢不會拖慢 UI 回應時間,並導致使用者體驗不佳。詳情請參閱 Android 訓練課程「在背景載入資料」。
要求讀取供應器的權限
如要執行任何類型的聯絡資訊提供者的搜尋作業,應用程式必須具備 READ_CONTACTS
權限。如要提出這項要求,請將此 <uses-permission>
元素新增至資訊清單檔案,做為 <manifest>
的子項:
<uses-permission android:name="android.permission.READ_CONTACTS" />
依名稱比對聯絡人,並列出結果
這項技術會嘗試將搜尋字串與聯絡供應器的 ContactsContract.Contacts
表格中聯絡人或聯絡人的名稱比對。您通常會在 ListView
中顯示結果,讓使用者從相符的聯絡人中選擇。
定義 ListView 和項目版面配置
如要在 ListView
中顯示搜尋結果,您需要一個主要版面配置檔案,定義整個 UI (包括 ListView
),以及一個項目版面配置檔案,定義 ListView
的一行。舉例來說,您可以使用下列 XML 建立主要版面配置檔案 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"/>
這個 XML 會使用內建的 Android ListView
小工具 android:id/list
。
使用下列 XML 定義項目版面配置檔案 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"/>
這個 XML 會使用內建的 Android TextView
小工具 android:text1
。
注意:本課程不會說明從使用者取得搜尋字串的 UI,因為您可能會想間接取得字串。例如,您可以讓使用者 這個選項,用於搜尋名稱與內送簡訊中字串相符的聯絡人。
您編寫的兩個版面配置檔案會定義顯示 ListView
的使用者介面。下一步是編寫使用此 UI 的程式碼,以便顯示聯絡人清單。
定義顯示聯絡人清單的 Fragment
如要顯示聯絡人清單,請先定義由 Activity
載入的 Fragment
。使用 Fragment
是更具彈性的技巧,因為您可以使用一個 Fragment
顯示清單,並使用另一個 Fragment
顯示使用者從清單中選擇的聯絡人詳細資料。使用這種方法,您可以將本課程介紹的其中一種技巧,與「擷取聯絡人的詳細資料」課程中的其中一種技巧結合。
如要瞭解如何從Fragment
Activity
,讀取訓練課程
使用 Fragment 建構動態 UI。
為協助您針對聯絡人供應程式編寫查詢,Android 架構提供名為 ContactsContract
的合約類別,其中定義了用於存取供應程式的實用常數和方法。使用這個類別時,您不必為內容 URI、資料表名稱或資料欄定義專屬常數。如要使用這個類別,請加入下列陳述式:
Kotlin
import android.provider.ContactsContract
Java
import android.provider.ContactsContract;
由於程式碼會使用 CursorLoader
從提供者擷取資料,因此您必須指定它實作載入器介面 LoaderManager.LoaderCallbacks
。此外,為了協助偵測使用者從搜尋結果清單中選取的聯絡人,請實作 AdapterView.OnItemClickListener
轉接介面。例如:
Kotlin
... import android.support.v4.app.Fragment import android.support.v4.app.LoaderManager import android.widget.AdapterView ... class ContactsFragment : Fragment(), LoaderManager.LoaderCallbacks<Cursor>, AdapterView.OnItemClickListener {
Java
... 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 {
定義全域變數
定義在程式碼其他部分中使用的全域變數:
Kotlin
... /* * Defines an array that contains column names to move from * the Cursor to the ListView. */ @SuppressLint("InlinedApi") private val FROM_COLUMNS: Array<String> = arrayOf( if ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)) { ContactsContract.Contacts.DISPLAY_NAME_PRIMARY } else { ContactsContract.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 val TO_IDS: IntArray = intArrayOf(android.R.id.text1) ... class ContactsFragment : Fragment(), LoaderManager.LoaderCallbacks<Cursor>, AdapterView.OnItemClickListener { ... // Define global mutable variables // Define a ListView object lateinit var contactsList: ListView // Define variables for the contact the user selects // The contact's _ID value var contactId: Long = 0 // The contact's LOOKUP_KEY var contactKey: String? = null // A content URI for the selected contact var contactUri: Uri? = null // An adapter that binds the result Cursor to the ListView private val cursorAdapter: SimpleCursorAdapter? = null
Java
... /* * 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 ? ContactsContract.Contacts.DISPLAY_NAME_PRIMARY : ContactsContract.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 contactsList; // Define variables for the contact the user selects // The contact's _ID value long contactId; // The contact's LOOKUP_KEY String contactKey; // A content URI for the selected contact Uri contactUri; // An adapter that binds the result Cursor to the ListView private SimpleCursorAdapter cursorAdapter; ...
注意:自
Contacts.DISPLAY_NAME_PRIMARY
需要 Android 3.0 (API 版本 11) 以上版本,請設定
應用程式的 minSdkVersion
到 10 以下版本會在以下位置產生 Android Lint 警告:
Android Studio。如要關閉這項警示,請新增註解
在 FROM_COLUMNS
定義之前 @SuppressLint("InlinedApi")
。
初始化 Fragment
初始化 Fragment
。新增 Android 系統所需的空白公開建構函式,並在回呼方法 onCreateView()
中加載 Fragment
物件的 UI。例如:
Kotlin
// A UI Fragment must inflate its View override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { // Inflate the fragment layout return inflater.inflate(R.layout.contact_list_fragment, container, false) }
Java
// 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); }
為 ListView 設定 CursorAdapter
設定 SimpleCursorAdapter
,將搜尋結果繫結至 ListView
。如要取得顯示聯絡人的 ListView
物件,您必須使用 Fragment
的父項活動呼叫 Activity.findViewById()
。呼叫 setAdapter()
時,請使用父項活動的 Context
。例如:
Kotlin
override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) ... // Gets the ListView from the View list of the parent activity activity?.also { contactsList = it.findViewById<ListView>(R.id.contact_list_view) // Gets a CursorAdapter cursorAdapter = SimpleCursorAdapter( it, R.layout.contact_list_item, null, FROM_COLUMNS, TO_IDS, 0 ) // Sets the adapter for the ListView contactsList.adapter = cursorAdapter } }
Java
public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); ... // Gets the ListView from the View list of the parent activity contactsList = (ListView) getActivity().findViewById(R.layout.contact_list_view); // Gets a CursorAdapter cursorAdapter = new SimpleCursorAdapter( getActivity(), R.layout.contact_list_item, null, FROM_COLUMNS, TO_IDS, 0); // Sets the adapter for the ListView contactsList.setAdapter(cursorAdapter); }
設定所選聯絡人監聽器
顯示搜尋結果時,您通常會希望讓使用者選取單一聯絡人,以便進一步處理。舉例來說,使用者點選聯絡人時
在地圖上顯示聯絡人的地址。為了提供這項功能,您首先將目前的 Fragment
定義為點擊事件監聽器,方法是指定該類別實作 AdapterView.OnItemClickListener
,如「定義顯示聯絡人清單的 Fragment」一節所示。
如要繼續設定事件監聽器,請呼叫 onActivityCreated()
中的 setOnItemClickListener()
方法,將事件監聽器繫結至 ListView
。例如:
Kotlin
fun onActivityCreated(savedInstanceState:Bundle) { ... // Set the item click listener to be the current fragment. contactsList.onItemClickListener = this ... }
Java
public void onActivityCreated(Bundle savedInstanceState) { ... // Set the item click listener to be the current fragment. contactsList.setOnItemClickListener(this); ... }
由於您指定目前的 Fragment
是
OnItemClickListener
:
ListView
,您現在需要實作其必要方法
onItemClick()
,
處理點擊事件我們會在成功的章節中說明。
定義投影
定義常數,該常數包含您要從查詢中傳回的資料欄。ListView
中的每個項目都會顯示聯絡人的顯示名稱,其中包含聯絡人名稱的主要形式。在 Android 3.0 (API 11 級別) 以上版本中,這個欄的名稱為 Contacts.DISPLAY_NAME_PRIMARY
;在先前版本中,其名稱為 Contacts.DISPLAY_NAME
。
SimpleCursorAdapter
繫結程序會使用資料欄 Contacts._ID
。「Contacts._ID
」和
搭配使用 LOOKUP_KEY
針對使用者選取的聯絡人建構內容 URI。
Kotlin
... @SuppressLint("InlinedApi") private val PROJECTION: Array<out String> = arrayOf( ContactsContract.Contacts._ID, ContactsContract.Contacts.LOOKUP_KEY, if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) ContactsContract.Contacts.DISPLAY_NAME_PRIMARY else ContactsContract.Contacts.DISPLAY_NAME )
Java
... @SuppressLint("InlinedApi") private static final String[] PROJECTION = { Contacts._ID, Contacts.LOOKUP_KEY, Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ? ContactsContract.Contacts.DISPLAY_NAME_PRIMARY : ContactsContract.Contacts.DISPLAY_NAME };
定義遊標資料欄索引的常數
如要從 Cursor
中的個別資料欄取得資料,您需要 Cursor
中的資料欄索引。您可以為 Cursor
欄的索引定義常數,因為索引與投影中欄名順序相同。例如:
Kotlin
// The column index for the _ID column private const val CONTACT_ID_INDEX: Int = 0 // The column index for the CONTACT_KEY column private const val CONTACT_KEY_INDEX: Int = 1
Java
// The column index for the _ID column private static final int CONTACT_ID_INDEX = 0; // The column index for the CONTACT_KEY column private static final int CONTACT_KEY_INDEX = 1;
指定選取條件
如要指定所需資料,請建立文字運算式和變數的組合 告知提供者要搜尋的資料欄和要尋找的值。
針對文字運算式,定義列出搜尋欄的常數。雖然這個運算式也可以包含值,但建議您使用「?」預留位置來表示值。在擷取期間,預留位置會替換為 陣列。使用「?」做為預留位置,可確保搜尋規格是由繫結而非 SQL 編譯產生。這項做法可避免惡意 SQL 注入攻擊。例如:
Kotlin
// Defines the text expression @SuppressLint("InlinedApi") private val SELECTION: String = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) "${ContactsContract.Contacts.DISPLAY_NAME_PRIMARY} LIKE ?" else "${ContactsContract.Contacts.DISPLAY_NAME} LIKE ?" ... // Defines a variable for the search string private val searchString: String = ... // Defines the array to hold values that replace the ? private val selectionArgs = arrayOf<String>(searchString)
Java
// 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 searchString; // Defines the array to hold values that replace the ? private String[] selectionArgs = { searchString };
定義 onItemClick() 方法
在上一節中,您已為 ListView
設定商品點擊事件監聽器。現在,請定義 AdapterView.OnItemClickListener.onItemClick()
方法,為事件監聽器實作動作:
Kotlin
override fun onItemClick(parent: AdapterView<*>, view: View?, position: Int, id: Long) { // Get the Cursor val cursor: Cursor? = (parent.adapter as? CursorAdapter)?.cursor?.apply { // Move to the selected contact moveToPosition(position) // Get the _ID value contactId = getLong(CONTACT_ID_INDEX) // Get the selected LOOKUP KEY contactKey = getString(CONTACT_KEY_INDEX) // Create the contact's content Uri contactUri = ContactsContract.Contacts.getLookupUri(contactId, mContactKey) /* * You can use contactUri as the content URI for retrieving * the details for a contact. */ } }
Java
@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 contactId = cursor.getLong(CONTACT_ID_INDEX); // Get the selected LOOKUP KEY contactKey = cursor.getString(CONTACT_KEY_INDEX); // Create the contact's content Uri contactUri = Contacts.getLookupUri(contactId, mContactKey); /* * You can use contactUri as the content URI for retrieving * the details for a contact. */ }
初始化載入器
由於您使用 CursorLoader
擷取資料,因此必須初始化背景執行緒和其他控制非同步擷取作業的變數。執行初始化作業是
onCreate()
為
如以下範例所示:
Kotlin
class ContactsFragment : Fragment(), LoaderManager.LoaderCallbacks<Cursor> { ... override fun onCreate(savedInstanceState: Bundle?) { // Always call the super method first super.onCreate(savedInstanceState) ... // Initializes the loader loaderManager.initLoader(0, null, this)
Java
public class ContactsFragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor> { ... // Called just before the Fragment displays its UI @Override public void onCreate(Bundle savedInstanceState) { // Always call the super method first super.onCreate(savedInstanceState); ... // Initializes the loader getLoaderManager().initLoader(0, null, this);
實作 onCreateLoader()
實作方法
onCreateLoader()
、
載入器架構後,載入器架構會在您呼叫
initLoader()
。
在 onCreateLoader()
中設定搜尋字串模式。如要將字串設為模式,請插入「%」(百分比) 字元,代表零個或多個字元的序列,或插入「_」(底線) 字元,代表單一字元,或同時插入這兩種字元。舉例來說,「%Jefferson%」模式會同時符合「Thomas Jefferson」和「Jefferson Davis」。
透過方法傳回新的 CursorLoader
。如要使用內容 URI,請使用 Contacts.CONTENT_URI
。這個 URI 參照整份資料表,如以下範例所示:
Kotlin
... override fun onCreateLoader(loaderId: Int, args: Bundle?): Loader<Cursor> { /* * Makes search string into pattern and * stores it in the selection array */ selectionArgs[0] = "%$mSearchString%" // Starts the query return activity?.let { return CursorLoader( it, ContactsContract.Contacts.CONTENT_URI, PROJECTION, SELECTION, selectionArgs, null ) } ?: throw IllegalStateException() }
Java
... @Override public Loader<Cursor> onCreateLoader(int loaderId, Bundle args) { /* * Makes search string into pattern and * stores it in the selection array */ selectionArgs[0] = "%" + searchString + "%"; // Starts the query return new CursorLoader( getActivity(), ContactsContract.Contacts.CONTENT_URI, PROJECTION, SELECTION, selectionArgs, null ); }
實作 onLoadFinished() 和 onLoaderReset()
實作
onLoadFinished()
方法。載入器架構呼叫
onLoadFinished()
聯絡人供應程式傳回查詢結果時。在這個方法中,將結果 Cursor
放入 SimpleCursorAdapter
。這樣就能自動更新
ListView
替換成以下搜尋結果:
Kotlin
override fun onLoadFinished(loader: Loader<Cursor>, cursor: Cursor) { // Put the result Cursor in the adapter for the ListView cursorAdapter?.swapCursor(cursor) }
Java
@Override public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { // Put the result Cursor in the adapter for the ListView cursorAdapter.swapCursor(cursor); }
當載入器架構偵測到結果 Cursor
含有過時資料時,系統會叫用 onLoaderReset()
方法。刪除
SimpleCursorAdapter
個現有參照
Cursor
。如果您沒有這樣做,載入器架構就不會回收 Cursor
,導致記憶體流失。例如:
Kotlin
override fun onLoaderReset(loader: Loader<Cursor>) { // Delete the reference to the existing Cursor cursorAdapter?.swapCursor(null) }
Java
@Override public void onLoaderReset(Loader<Cursor> loader) { // Delete the reference to the existing Cursor cursorAdapter.swapCursor(null); }
您現在已完成應用程式的重點部分,可比對搜尋字串與聯絡人姓名並傳回
在 ListView
的結果中。使用者可以按一下聯絡人名稱加以選取。
這會觸發事件監聽器,讓您進一步處理聯絡人的資料。例如,您可以擷取聯絡人的詳細資料。如要瞭解操作方式,請繼續閱讀
課程:擷取聯絡人的詳細資料。
如要進一步瞭解搜尋使用者介面,請參閱 API 指南的「建立搜尋介面」一節。
本課程其餘部分示範了在 聯絡人供應程式。
依特定資料類型比對聯絡人
這項技巧可讓你指定要比對的資料類型。擷取中 「名稱」就是這類型查詢的特定範例,不過您也可以對任何類型的查詢執行這項指令 與聯絡人相關的詳細資料資料舉例來說,您可以擷取具有 特定郵遞區號;在此範例中,搜尋字串必須與郵遞區號中儲存的資料相符 列。
如要實作這類擷取作業,請先實作下列程式碼,如前面各節所述:
- 要求讀取提供者的權限。
- 定義 ListView 和項目版面配置。
- 定義用於顯示聯絡人清單的片段。
- 定義全域變數。
- 初始化 Fragment。
- 為 ListView 設定 CursorAdapter。
- 設定所選聯絡人監聽器。
-
定義遊標資料欄索引的常數。
雖然您是從不同的資料表擷取資料,但 投影相同,因此您可以對遊標使用相同的索引。
- 定義 onItemClick() 方法。
- 初始化載入器。
- 實作 onLoadFinished() 和 onLoaderReset()。
以下步驟會顯示需要的額外程式碼,以便將搜尋字串與特定類型的詳細資料相符,並顯示結果。
選擇資料類型和資料表
如要搜尋特定類型的詳細資料,您必須知道該資料類型的自訂 MIME 類型值。每個資料類型都有專屬的 MIME 類型值,由與資料類型相關聯的 ContactsContract.CommonDataKinds
子類別中的常數 CONTENT_ITEM_TYPE
定義。這些子類別的名稱會指出其資料類型;例如:電子郵件的子類別
資料為 ContactsContract.CommonDataKinds.Email
,自訂 MIME
電子郵件資料的型別是由常數定義
Email.CONTENT_ITEM_TYPE
。
請使用 ContactsContract.Data
表格進行搜尋。所有的
投影、選取子句和排序順序所需的常數位於 或
沿用自這個資料表
定義投影
如要定義投影,請選擇一或多個定義於
ContactsContract.Data
或其繼承的類別。
聯絡人供應商在 ContactsContract.Data
之間執行隱式彙整
和其他資料表,然後才傳回資料列。例如:
Kotlin
@SuppressLint("InlinedApi") private val PROJECTION: Array<out String> = arrayOf( /* * The detail data row ID. To make a ListView work, * this column is required. */ ContactsContract.Data._ID, // The primary display name if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) ContactsContract.Data.DISPLAY_NAME_PRIMARY else ContactsContract.Data.DISPLAY_NAME, // The contact's _ID, to construct a content URI ContactsContract.Data.CONTACT_ID, // The contact's LOOKUP_KEY, to construct a content URI ContactsContract.Data.LOOKUP_KEY )
Java
@SuppressLint("InlinedApi") private static final String[] PROJECTION = { /* * The detail data row ID. To make a ListView work, * this column is required. */ ContactsContract.Data._ID, // The primary display name Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ? ContactsContract.Data.DISPLAY_NAME_PRIMARY : ContactsContract.Data.DISPLAY_NAME, // The contact's _ID, to construct a content URI ContactsContract.Data.CONTACT_ID, // The contact's LOOKUP_KEY, to construct a content URI ContactsContract.Data.LOOKUP_KEY // A permanent link to the contact };
定義搜尋條件
如要搜尋特定類型資料中的字串,請建立選取子句 包括:
-
包含搜尋字串的資料欄名稱。此名稱會因資料類型而異
因此您需要找出
對應資料類型的
ContactsContract.CommonDataKinds
然後從子類別中選擇資料欄名稱例如,如要搜尋電子郵件地址,請使用Email.ADDRESS
資料欄。 - 搜尋字串本身,以「?」字元。
-
包含自訂 MIME 類型值的資料欄名稱。這個名稱一律為
Data.MIMETYPE
。 -
資料類型的自訂 MIME 類型值。如前所述,這是常數
CONTENT_ITEM_TYPE
是ContactsContract.CommonDataKinds
子類別。舉例來說,電子郵件資料的 MIME 類型值為Email.CONTENT_ITEM_TYPE
。串連 「'
」(單引號) 字元加到常數的開頭和結尾;否則 供應器會將值解讀為變數名稱,而非字串值。 您不需要為這個值使用預留位置,因為您使用的是常數,而非使用者提供的值。
例如:
Kotlin
/* * Constructs search criteria from the search string * and email MIME type */ private val SELECTION: String = /* * 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. */ "${ContactsContract.Data.MIMETYPE } = '${Email.CONTENT_ITEM_TYPE}'"
Java
/* * 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. */ ContactsContract.Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'";
接著,定義包含選取引數的變數:
Kotlin
private var searchString: String? = null private val selectionArgs: Array<String> = arrayOf("")
Java
String searchString; String[] selectionArgs = { "" };
實作 onCreateLoader()
指定資料與搜尋方式後,請在
實作 onCreateLoader()
。
使用投影、選取文字運算式和選取陣列做為引數,從這個方法傳回新的 CursorLoader
。如果是內容 URI,請使用
Data.CONTENT_URI
。例如:
Kotlin
override fun onCreateLoader(id: Int, args: Bundle?): Loader<Cursor> { // OPTIONAL: Makes search string into pattern searchString = "%$mSearchString%" searchString?.also { // Puts the search string into the selection criteria selectionArgs[0] = it } // Starts the query return activity?.let { CursorLoader( it, ContactsContract.Data.CONTENT_URI, PROJECTION, SELECTION, selectionArgs, null ) } ?: throw IllegalStateException() }
Java
@Override public Loader<Cursor> onCreateLoader(int loaderId, Bundle args) { // OPTIONAL: Makes search string into pattern searchString = "%" + searchString + "%"; // Puts the search string into the selection criteria selectionArgs[0] = searchString; // Starts the query return new CursorLoader( getActivity(), Data.CONTENT_URI, PROJECTION, SELECTION, selectionArgs, null ); }
這些程式碼片段是簡易反向查詢的基礎,主要用於特定類型的詳細查詢 資料。如果應用程式著重於特定類型的資料 (例如電子郵件),且您希望使用者能夠取得與資料相關聯的名稱,這就是最佳的做法。
根據任何類型的資料比對聯絡人
根據任何類型的資料擷取聯絡人時,如果聯絡人的任何資料與搜尋字串相符 (包括姓名、電子郵件地址、郵遞地址、電話號碼等),系統就會傳回該聯絡人。以便取得大量的搜尋結果。舉例來說,如果搜尋字串是「Doe」,搜尋任何資料類型都會傳回「John Doe」聯絡人,也會傳回住在「Doe Street」的聯絡人。
如要執行這類型的擷取,請先實作下列程式碼,如 前幾節:
- 要求讀取提供者的權限。
- 定義 ListView 和項目版面配置。
- 定義用於顯示聯絡人清單的片段。
- 定義全域變數。
- 初始化 Fragment。
- 為 ListView 設定 CursorAdapter。
- 設定所選聯絡人的監聽器。
- 定義投影。
-
定義遊標資料欄索引的常數。
針對這類擷取作業,您會使用「依名稱比對聯絡人並列出結果」一節中使用的相同表格。使用 相同的資料欄索引
- 定義 onItemClick() 方法。
- 初始化載入器。
- 實作 onLoadFinished() 和 onLoaderReset()。
下列步驟將說明要比對搜尋字串到 任何類型的資料並顯示結果
移除選取條件
請勿定義 SELECTION
常數或 mSelectionArgs
變數。
這些內容不會用於這類擷取作業。
實作 onCreateLoader()
實作 onCreateLoader()
方法,傳回新的 CursorLoader
。您不需要將搜尋字串轉換成格式,因為聯絡人提供者會
為此,我們會自動執行動作使用 Contacts.CONTENT_FILTER_URI
做為基準 URI,並透過呼叫 Uri.withAppendedPath()
將搜尋字串附加至其中。使用這個 URI 會自動觸發任何資料類型的搜尋作業,如以下範例所示:
Kotlin
override fun onCreateLoader(loaderId: Int, args: Bundle?): Loader<Cursor> { /* * Appends the search string to the base URI. Always * encode search strings to ensure they're in proper * format. */ val contentUri: Uri = Uri.withAppendedPath( ContactsContract.Contacts.CONTENT_FILTER_URI, Uri.encode(searchString) ) // Starts the query return activity?.let { CursorLoader( it, contentUri, PROJECTION2, null, null, null ) } ?: throw IllegalStateException() }
Java
@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(searchString)); // Starts the query return new CursorLoader( getActivity(), contentUri, PROJECTION, null, null, null ); }
這些程式碼片段是應用程式廣泛搜尋聯絡人供應器的基礎。如果應用程式要實作類似 聯絡人應用程式的聯絡人清單畫面。