Pelajaran ini menampilkan cara mengambil daftar kontak yang datanya cocok dengan semua atau sebagian data. string penelusuran, menggunakan teknik berikut:
- Mencocokkan nama kontak
- Ambil daftar kontak dengan mencocokkan string penelusuran dengan semua atau sebagian data nama kontak. Penyedia Kontak mendukung beberapa instance nama yang sama, sehingga teknik ini dapat menampilkan daftar kecocokan.
- Mencocokkan jenis data tertentu, seperti nomor telepon
- Ambil daftar kontak dengan mencocokkan string penelusuran dengan jenis data detail tertentu, seperti alamat email. Misalnya, teknik ini memungkinkan Anda membuat daftar semua kontak yang alamat emailnya cocok dengan string penelusuran.
- Mencocokkan segala jenis data
- Ambil daftar kontak dengan mencocokkan string penelusuran dengan sembarang jenis data detail, termasuk nama, nomor telepon, alamat jalan, alamat email, dan sebagainya. Misalnya, teknik ini memungkinkan Anda menerima jenis data apa pun untuk string pencarian kontak yang datanya cocok dengan {i>string<i}.
Catatan: Semua contoh dalam pelajaran ini menggunakan
CursorLoader
untuk mengambil data dari Penyedia
Kontak. CursorLoader
menjalankan kuerinya pada
thread yang terpisah dari thread UI. Hal ini memastikan bahwa kueri tidak memperlambat UI
waktu respons dan menyebabkan
pengalaman pengguna yang buruk. Untuk informasi selengkapnya, lihat
kelas pelatihan
Memuat Data di Latar Belakang.
Meminta izin untuk membaca penyedia
Untuk melakukan jenis penelusuran apa pun pada Penyedia Kontak, aplikasi Anda harus memiliki
izin READ_CONTACTS
.
Untuk meminta ini, tambahkan
<uses-permission>
ke file manifes sebagai elemen turunan dari
<manifest>
:
<uses-permission android:name="android.permission.READ_CONTACTS" />
Mencocokkan kontak menurut nama dan mencantumkan hasilnya
Teknik ini mencoba mencocokkan string penelusuran dengan nama kontak dalam tabel ContactsContract.Contacts
Penyedia Kontak. Anda biasanya ingin
untuk menampilkan hasil di ListView
, agar pengguna dapat memilih di antara
kontak yang cocok.
Menentukan ListView dan tata letak item
Untuk menampilkan hasil penelusuran dalam ListView
, Anda memerlukan file tata letak utama
yang menentukan seluruh UI termasuk ListView
, dan tata letak item
yang menentukan satu baris ListView
. Misalnya, Anda dapat membuat
file tata letak utama res/layout/contacts_list_view.xml
dengan
XML berikut:
<?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 ini menggunakan widget ListView
Android bawaan
android:id/list
.
Tentukan file tata letak item contacts_list_item.xml
dengan XML berikut:
<?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 ini menggunakan widget TextView
Android bawaan
android:text1
.
Catatan: Pelajaran ini tidak menjelaskan UI untuk mendapatkan string penelusuran dari karena Anda mungkin ingin mendapatkan string secara tidak langsung. Misalnya, Anda dapat memberikan kepada pengguna opsi untuk mencari kontak yang namanya cocok dengan {i>string<i} dalam pesan teks yang masuk.
Kedua file tata letak yang Anda tulis menentukan antarmuka pengguna yang menampilkan
ListView
. Langkah berikutnya adalah menulis kode yang menggunakan UI ini untuk menampilkan
daftar kontak.
Menetapkan Fragment yang menampilkan daftar kontak
Untuk menampilkan daftar kontak, mulailah dengan menentukan Fragment
yang dimuat oleh Activity
. Menggunakan
Fragment
adalah teknik yang lebih fleksibel, karena Anda dapat menggunakan
satu Fragment
untuk menampilkan daftar dan
Fragment
untuk menampilkan detail kontak yang digunakan pengguna
dipilih dari daftar. Dengan pendekatan ini, Anda dapat menggabungkan
salah satu teknik yang disajikan dalam
pelajaran ini, dengan salah satu dari pelajaran
Mengambil detail kontak.
Untuk mempelajari cara menggunakan satu atau beberapa objek Fragment
dari
Activity
, baca kelas pelatihan
Membangun UI dinamis dengan Fragment.
Untuk membantu Anda menulis kueri terhadap Penyedia Kontak, framework Android menyediakan
class kontrak yang disebut ContactsContract
, yang menentukan fungsi
untuk mengakses penyedia. Saat menggunakan class ini, Anda tidak perlu menentukan konstanta Anda sendiri untuk URI konten, nama tabel, atau kolom. Untuk menggunakan class ini,
sertakan pernyataan berikut:
Kotlin
import android.provider.ContactsContract
Java
import android.provider.ContactsContract;
Karena kode ini menggunakan CursorLoader
untuk mengambil data
dari penyedia, Anda harus menentukan bahwa kode tersebut mengimplementasikan antarmuka loader
LoaderManager.LoaderCallbacks
. Juga, untuk membantu mendeteksi kontak
pengguna memilih dari daftar hasil penelusuran, menerapkan antarmuka adaptor
AdapterView.OnItemClickListener
. Contoh:
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 {
Menentukan variabel global
Tentukan variabel global yang digunakan di bagian lain kode:
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; ...
Catatan: Karena
Contacts.DISPLAY_NAME_PRIMARY
memerlukan Android 3.0 (API versi 11) atau yang lebih baru, yang menyetel
minSdkVersion
aplikasi ke 10 atau yang lebih rendah menghasilkan peringatan Android Lint di
Android Studio. Untuk menonaktifkan peringatan ini, tambahkan anotasi
@SuppressLint("InlinedApi")
sebelum definisi FROM_COLUMNS
.
Menginisialisasi Fragment
Inisialisasi Fragment
. Tambahkan konstruktor publik kosong
yang diperlukan oleh sistem Android, dan perluas UI objek
Fragment
dalam metode callback onCreateView()
.
Contoh:
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); }
Menyiapkan CursorAdapter untuk ListView
Siapkan SimpleCursorAdapter
yang mengikat hasil penelusuran ke ListView
. Untuk mendapatkan objek ListView
yang menampilkan kontak, Anda harus memanggil Activity.findViewById()
menggunakan aktivitas induk
Fragment
. Gunakan Context
dari
aktivitas induk saat Anda memanggil setAdapter()
.
Contoh:
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); }
Menetapkan pemroses kontak yang dipilih
Saat menampilkan hasil penelusuran, biasanya Anda perlu mengizinkan pengguna memilih satu kontak untuk diproses lebih lanjut. Misalnya, saat pengguna mengeklik kontak, Anda dapat
menampilkan alamat kontak pada peta. Untuk menyediakan fitur ini, Anda terlebih dahulu mendefinisikan
Fragment
sebagai pemroses klik dengan menetapkan bahwa class tersebut
mengimplementasikan AdapterView.OnItemClickListener
, seperti yang ditunjukkan pada bagian
Menentukan Fragment yang menampilkan daftar kontak.
Untuk melanjutkan penyiapan pemroses, ikatkan ke ListView
dengan
memanggil metode setOnItemClickListener()
di onActivityCreated()
. Contoh:
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); ... }
Karena Anda menentukan bahwa Fragment
saat ini adalah
OnItemClickListener
untuk
ListView
, Anda sekarang harus mengimplementasikan metode yang diperlukan
onItemClick()
, yang
menangani peristiwa klik. Hal ini dijelaskan di bagian selanjutnya.
Menentukan proyeksi
Tentukan konstanta yang berisi kolom-kolom yang ingin Anda tampilkan dari kueri Anda. Setiap item di
ListView
menampilkan nama tampilan kontak,
yang berisi bentuk utama
nama kontak. Di Android 3.0 (API versi 11) dan yang lebih baru,
nama kolom ini adalah
Contacts.DISPLAY_NAME_PRIMARY
; dalam versi sebelumnya, namanya
Contacts.DISPLAY_NAME
.
Kolom Contacts._ID
digunakan oleh
Proses binding SimpleCursorAdapter
.
Contacts._ID
dan
LOOKUP_KEY
digunakan bersama untuk
membuat URI konten untuk kontak yang dipilih pengguna.
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 };
Menentukan konstanta untuk indeks kolom Cursor
Untuk mendapatkan data dari kolom tertentu dalam Cursor
, Anda memerlukan
indeks kolom dalam Cursor
. Anda dapat menentukan konstanta untuk indeks kolom Cursor
, karena indeks ini sama dengan urutan nama kolom dalam proyeksi Anda. Contoh:
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;
Menetapkan kriteria pemilihan
Untuk menentukan data yang diinginkan, buat kombinasi ekspresi teks dan variabel yang memberi tahu penyedia kolom data yang akan ditelusuri dan nilai yang akan ditemukan.
Untuk ekspresi teks, tentukan konstanta yang mencantumkan kolom penelusuran. Meskipun ini ekspresi reguler dapat berisi nilai juga, praktik yang disukai adalah mewakili nilai-nilai dengan "?" {i>placeholder<i}. Selama pengambilan data, placeholder diganti dengan nilai dari array. Menggunakan "?" sebagai placeholder memastikan bahwa spesifikasi penelusuran dihasilkan melalui binding bukan pada kompilasi SQL. Praktik ini menghilangkan kemungkinan terjadinya tanpa injeksi. Contoh:
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 };
Menentukan metode onItemClick()
Di bagian sebelumnya, Anda menetapkan pemroses klik item untuk ListView
.
Sekarang, terapkan tindakan untuk pemroses dengan menentukan metode
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. */ }
Menginisialisasi loader
Karena Anda menggunakan CursorLoader
untuk mengambil data,
Anda harus menginisialisasi thread latar belakang dan variabel lain yang mengontrol pengambilan
asinkron. Lakukan inisialisasi dalam
onCreate()
seperti
ditunjukkan pada contoh berikut:
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);
Menerapkan onCreateLoader()
Mengimplementasikan metode
Halo onCreateLoader()
,
yang dipanggil oleh kerangka kerja loader segera setelah Anda memanggil
initLoader()
.
Di onCreateLoader()
,
siapkan pola string penelusuran. Untuk membuat string menjadi pola, sisipkan "%"
(persen) karakter untuk mewakili rangkaian nol atau lebih karakter, atau "_" (garis bawah)
karakter untuk mewakili satu karakter, atau keduanya. Misalnya, pola "%Jefferson%"
akan cocok dengan "Thomas Jefferson" dan "Jefferson Davis".
Tampilkan CursorLoader
baru dari metode. Untuk URI
konten, gunakan Contacts.CONTENT_URI
.
URI ini merujuk ke seluruh tabel, seperti yang ditunjukkan dalam contoh berikut:
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 ); }
Mengimplementasikan onLoadFinished() dan onLoaderReset()
Implementasikan
onLoadFinished()
. Framework loader memanggil
onLoadFinished()
saat Penyedia Kontak menampilkan hasil kueri. Dalam metode ini, tempatkan
hasil Cursor
dalam
SimpleCursorAdapter
. Hal ini secara otomatis memperbarui
ListView
dengan hasil penelusuran:
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); }
Metode onLoaderReset()
dipanggil saat framework loader mendeteksi bahwa
hasil Cursor
berisi data yang usang. Hapus referensi
SimpleCursorAdapter
ke Cursor
yang ada. Jika tidak, framework loader tidak akan
melakukan daur ulang Cursor
, yang menyebabkan kebocoran memori. Contoh:
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); }
Anda sekarang memiliki bagian penting dari aplikasi yang mencocokkan string penelusuran dengan nama kontak dan menampilkan
hasilnya di ListView
. Pengguna dapat mengklik nama kontak untuk memilihnya.
Hal ini akan memicu pemroses, yang memungkinkan Anda menangani data kontak lebih jauh. Misalnya,
Anda dapat mengambil detail kontak. Untuk mempelajari cara melakukannya, lanjutkan ke langkah
Mengambil detail untuk kontak.
Untuk mempelajari antarmuka pengguna penelusuran lebih lanjut, baca panduan API Membuat antarmuka penelusuran.
Bagian selanjutnya dalam pelajaran ini menunjukkan cara lain untuk menemukan kontak di Penyedia Kontak.
Mencocokkan kontak menurut jenis data tertentu
Teknik ini memungkinkan Anda menetapkan jenis data yang ingin dicocokkan. Pengambilan data menurut nama adalah contoh spesifik dari jenis kueri ini, tetapi Anda juga dapat melakukannya untuk jenis data detail apa pun yang terkait dengan kontak. Misalnya, Anda bisa mengambil kontak yang memiliki kode pos tertentu; dalam hal ini, string penelusuran harus cocok dengan data yang disimpan dalam baris.
Untuk menerapkan jenis pengambilan ini, pertama-tama terapkan kode berikut, seperti yang tercantum di bagian sebelumnya:
- Meminta Izin untuk Membaca Penyedia.
- Menentukan ListView dan tata letak item.
- Menetapkan Fragment yang menampilkan daftar kontak.
- Menentukan variabel global.
- Menginisialisasi Fragment.
- Menyiapkan CursorAdapter untuk ListView.
- Menetapkan pemroses kontak yang dipilih.
-
Menentukan konstanta untuk indeks kolom Cursor.
Meskipun Anda mengambil data dari tabel yang berbeda, urutan kolom dalam proyeksi ini tetap sama, sehingga Anda dapat menggunakan indeks yang sama untuk Cursor.
- Menentukan metode onItemClick().
- Menginisialisasi loader.
- Menerapkan onLoadFinished() dan onLoaderReset().
Langkah-langkah berikut menunjukkan kode tambahan yang Anda perlukan untuk mencocokkan string penelusuran dengan jenis data detail tertentu dan menampilkan hasilnya.
Memilih jenis data dan tabel
Untuk menelusuri jenis data detail tertentu, Anda harus mengetahui nilai jenis MIME kustom
untuk tipe data. Setiap jenis data memiliki jenis MIME yang unik
yang ditentukan oleh konstanta CONTENT_ITEM_TYPE
di subclass dari
ContactsContract.CommonDataKinds
yang terkait dengan jenis data.
Subclass memiliki nama yang menunjukkan jenis datanya; misalnya, subclass untuk data email adalah ContactsContract.CommonDataKinds.Email
, dan jenis MIME kustom untuk data email ditentukan oleh konstanta Email.CONTENT_ITEM_TYPE
.
Gunakan tabel ContactsContract.Data
untuk penelusuran Anda. Semua
konstanta yang diperlukan untuk proyeksi, klausa pemilihan, dan urutan pengurutan ditentukan dalam atau
diwarisi oleh tabel ini.
Menentukan proyeksi
Untuk mendefinisikan proyeksi, pilih satu atau lebih kolom yang ditentukan di
ContactsContract.Data
atau class yang diwarisinya. Penyedia
Kontak melakukan penggabungan implisit antara ContactsContract.Data
dan tabel lainnya sebelum menampilkan baris. Contoh:
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 };
Menentukan kriteria penelusuran
Untuk menelusuri string dalam jenis data tertentu, buatlah klausa pemilihan dari berikut ini:
-
Nama kolom yang berisi string penelusuran Anda. Nama ini bervariasi menurut jenis data,
sehingga Anda perlu menemukan subclass
ContactsContract.CommonDataKinds
yang sesuai dengan jenis datanya, lalu memilih nama kolom dari subclass tersebut. Misalnya, untuk menelusuri alamat email, gunakan kolomEmail.ADDRESS
. - String penelusuran itu sendiri, direpresentasikan sebagai karakter "?" dalam klausa pemilihan.
-
Nama kolom yang berisi nilai jenis MIME kustom. Nama ini selalu
Data.MIMETYPE
. -
Nilai jenis MIME kustom untuk jenis data itu. Seperti dijelaskan sebelumnya, ini adalah konstanta
CONTENT_ITEM_TYPE
dalam SubclassContactsContract.CommonDataKinds
. Misalnya, MIME nilai jenis untuk data email adalahEmail.CONTENT_ITEM_TYPE
. Tempatkan nilai ini di antara tanda kutip tunggal dengan menggabungkan karakter "'
" (tanda kutip tunggal) ke awal dan akhir konstanta; jika tidak, penyedia akan menafsirkan nilai itu sebagai nama variabel, bukan sebagai nilai string. Anda tidak perlu menggunakan placeholder untuk nilai ini, karena Anda menggunakan konstanta, bukan nilai yang disediakan pengguna.
Contoh:
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 + "'";
Selanjutnya, tentukan variabel yang akan memuat argumen pemilihan:
Kotlin
private var searchString: String? = null private val selectionArgs: Array<String> = arrayOf("")
Java
String searchString; String[] selectionArgs = { "" };
Menerapkan onCreateLoader()
Setelah menetapkan data yang diinginkan dan cara menemukannya, tentukan kueri
implementasi onCreateLoader()
.
Tampilkan CursorLoader
baru dari
pilihan, menggunakan proyeksi, ekspresi teks pemilihan, dan array pilihan
argumen. Untuk URI konten, gunakan
Data.CONTENT_URI
. Contoh:
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 ); }
Cuplikan kode ini adalah dasar dari pencarian terbalik sederhana yang didasarkan pada jenis data detail tertentu. Ini adalah teknik terbaik yang bisa digunakan jika aplikasi Anda berfokus pada jenis data tertentu, seperti email, dan Anda ingin mengizinkan pengguna mendapatkan nama yang terkait dengan data tertentu.
Mencocokkan kontak menurut sembarang jenis data
Mengambil kontak berdasarkan semua jenis data akan menampilkan kontak jika ada datanya yang cocok dengan string penelusuran, termasuk nama, alamat email, alamat pos, nomor telepon, dan sebagainya. Cara ini menghasilkan hasil penelusuran yang luas. Misalnya, jika string penelusuran Anda adalah "Indra", maka menelusuri sembarang jenis data akan menampilkan kontak "Dewi Indra"; string penelusuran ini juga menampilkan kontak yang tinggal di "Jalan Indra".
Untuk menerapkan jenis pengambilan ini, pertama-tama terapkan kode berikut, seperti yang tercantum di bagian sebelumnya:
- Meminta Izin untuk Membaca Penyedia.
- Menentukan ListView dan tata letak item.
- Menetapkan Fragment yang menampilkan daftar kontak.
- Menentukan variabel global.
- Menginisialisasi Fragment.
- Menyiapkan CursorAdapter untuk ListView.
- Menetapkan pemroses kontak yang dipilih.
- Menentukan proyeksi.
-
Menentukan konstanta untuk indeks kolom Cursor.
Untuk jenis pengambilan ini, Anda menggunakan tabel yang sama dengan yang Anda gunakan di bagian Cocokkan kontak menurut nama dan cantumkan hasilnya. Gunakan indeks kolom yang sama juga.
- Menentukan metode onItemClick().
- Menginisialisasi loader.
- Menerapkan onLoadFinished() dan onLoaderReset().
Langkah-langkah berikut menunjukkan kode tambahan yang Anda perlukan untuk mencocokkan string penelusuran dengan jenis data apa pun dan menampilkan hasilnya.
Menghapus kriteria pemilihan
Jangan menentukan konstanta SELECTION
atau variabel mSelectionArgs
.
Keduanya tidak digunakan dalam jenis pengambilan ini.
Menerapkan onCreateLoader()
Mengimplementasikan onCreateLoader()
, yang menampilkan CursorLoader
baru.
Anda tidak perlu mengubah string penelusuran menjadi sebuah pola, karena Penyedia Kontak melakukannya
secara otomatis. Gunakan
Contacts.CONTENT_FILTER_URI
sebagai URI dasar, lalu tambahkan string penelusuran Anda dengan memanggil
Uri.withAppendedPath()
. Penggunaan URI ini secara otomatis memicu penelusuran untuk jenis data apa pun, seperti yang ditunjukkan dalam contoh berikut:
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 ); }
Cuplikan kode ini adalah dasar dari aplikasi yang melakukan penelusuran yang luas terhadap Penyedia Kontak. Teknik ini berguna untuk aplikasi yang ingin mengimplementasikan fungsi yang mirip dengan Layar daftar kontak pada aplikasi Orang.