این درس به شما نشان میدهد که چگونه با استفاده از تکنیکهای زیر، فهرستی از مخاطبین را که دادههای آنها با تمام یا بخشی از یک رشته جستجو مطابقت دارد، بازیابی کنید:
- نام مخاطبین را مطابقت دهید
- با تطبیق رشته جستجو با تمام یا بخشی از اطلاعات نام مخاطب، فهرستی از مخاطبین را بازیابی کنید. ارائه دهنده مخاطبین به چندین نمونه با یک نام اجازه می دهد، بنابراین این تکنیک می تواند لیستی از موارد مشابه را برگرداند.
- نوع خاصی از داده ها را مطابقت دهید، مانند شماره تلفن
- فهرستی از مخاطبین را با تطبیق رشته جستجو با نوع خاصی از داده های جزئیات مانند آدرس ایمیل بازیابی کنید. به عنوان مثال، این تکنیک به شما امکان می دهد تمام مخاطبینی را که آدرس ایمیل آنها با رشته جستجو مطابقت دارد فهرست کنید.
- هر نوع داده را مطابقت دهید
- فهرستی از مخاطبین را با تطبیق رشته جستجو با هر نوع اطلاعات جزئی، از جمله نام، شماره تلفن، آدرس خیابان، آدرس ایمیل و غیره بازیابی کنید. برای مثال، این تکنیک به شما اجازه میدهد تا هر نوع دادهای را برای رشته جستجو بپذیرید و سپس مخاطبینی را که دادههای آنها با رشته مطابقت دارد فهرست کنید.
توجه: تمام مثالهای این درس از CursorLoader
برای بازیابی اطلاعات از Contacts Provider استفاده میکنند. یک CursorLoader
پرس و جوی خود را روی رشته ای که از رشته رابط کاربری جدا است اجرا می کند. این تضمین می کند که پرس و جو زمان پاسخ UI را کاهش نمی دهد و باعث تجربه کاربری ضعیف نمی شود. برای اطلاعات بیشتر، کلاس آموزشی Android Loading Data in the Background را ببینید.
درخواست اجازه برای خواندن ارائه دهنده
برای انجام هر نوع جستجوی ارائه دهنده مخاطبین، برنامه شما باید مجوز READ_CONTACTS
داشته باشد. برای درخواست، این عنصر <uses-permission>
را به عنوان عنصر فرزند <manifest>
به فایل مانیفست خود اضافه کنید:
<uses-permission android:name="android.permission.READ_CONTACTS" />
یک مخاطب را با نام مطابقت دهید و نتایج را فهرست کنید
این تکنیک سعی می کند یک رشته جستجو را با نام مخاطب یا مخاطبین در جدول ContactsContract.Contacts
ارائه دهنده تماس مطابقت دهد. شما معمولاً می خواهید نتایج را در ListView
نمایش دهید تا به کاربر اجازه دهید از بین مخاطبین همسان انتخاب کند.
ListView و طرح بندی آیتم ها را تعریف کنید
برای نمایش نتایج جستجو در ListView
، به یک فایل طرح بندی اصلی نیاز دارید که کل رابط کاربری شامل ListView
را تعریف کند، و یک فایل طرح بندی مورد که یک خط از ListView
را تعریف کند. برای مثال، میتوانید فایل طرحبندی اصلی res/layout/contacts_list_view.xml
را با 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
استفاده می کند.
فایل طرح بندی مورد contacts_list_item.xml
را با 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
استفاده می کند.
توجه: این درس رابط کاربری برای دریافت رشته جستجو از کاربر را توصیف نمی کند، زیرا ممکن است بخواهید رشته را به طور غیر مستقیم دریافت کنید. برای مثال، میتوانید به کاربر گزینهای بدهید تا مخاطبینی را که نامشان با یک رشته در پیام متنی دریافتی مطابقت دارد، جستجو کند.
دو فایل طرحبندی که نوشتهاید، یک رابط کاربری را تعریف میکنند که ListView
را نشان میدهد. مرحله بعدی نوشتن کدی است که از این رابط کاربری برای نمایش لیستی از مخاطبین استفاده می کند.
قطعه ای را تعریف کنید که لیست مخاطبین را نمایش دهد
برای نمایش لیست مخاطبین، با تعریف Fragment
که توسط یک Activity
بارگیری می شود شروع کنید. استفاده از Fragment
تکنیک انعطافپذیرتری است، زیرا میتوانید از یک Fragment
برای نمایش لیست و از Fragment
دوم برای نمایش جزئیات مخاطبی که کاربر از لیست انتخاب میکند استفاده کنید. با استفاده از این رویکرد، می توانید یکی از تکنیک های ارائه شده در این درس را با یکی از تکنیک های درس ترکیب کنید. جزئیات را برای یک مخاطب بازیابی کنید .
برای یادگیری نحوه استفاده از یک یا چند شیء Fragment
از یک Activity
، کلاس آموزشی Build a dynamic UI with Fragments را بخوانید.
برای کمک به شما در نوشتن پرسوجوها در برابر ارائهدهنده مخاطبین، چارچوب Android یک کلاس قرارداد به نام ContactsContract
ارائه میکند که ثابتها و روشهای مفیدی را برای دسترسی به ارائهدهنده تعریف میکند. وقتی از این کلاس استفاده میکنید، نیازی نیست که ثابتهای خود را برای URI محتوا، نام جدول یا ستونها تعریف کنید. برای استفاده از این کلاس، عبارت زیر را وارد کنید:
کاتلین
import android.provider.ContactsContract
جاوا
import android.provider.ContactsContract;
از آنجایی که کد CursorLoader
برای بازیابی دادهها از ارائهدهنده استفاده میکند، باید مشخص کنید که رابط بارگیری LoaderManager.LoaderCallbacks
را پیادهسازی کند. همچنین، برای کمک به شناسایی مخاطبی که کاربر از لیست نتایج جستجو انتخاب می کند، رابط آداپتور AdapterView.OnItemClickListener
پیاده سازی کنید. به عنوان مثال:
کاتلین
... import android.support.v4.app.Fragment import android.support.v4.app.LoaderManager import android.widget.AdapterView ... class ContactsFragment : Fragment(), LoaderManager.LoaderCallbacks<Cursor>, 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 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
جاوا
... /* * 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 ایجاد می کند. برای خاموش کردن این هشدار، حاشیه نویسی @SuppressLint("InlinedApi")
قبل از تعریف FROM_COLUMNS
اضافه کنید.
Fragment را مقداردهی اولیه کنید
Fragment
را راه اندازی کنید. سازنده خالی و عمومی مورد نیاز سیستم اندروید را اضافه کنید و UI شی Fragment
را در روش callback onCreateView()
اضافه کنید. به عنوان مثال:
کاتلین
// 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) }
جاوا
// 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); }
CursorAdapter را برای ListView تنظیم کنید
SimpleCursorAdapter
را تنظیم کنید که نتایج جستجو را به ListView
متصل می کند. برای دریافت شی ListView
که مخاطبین را نمایش می دهد، باید با استفاده از فعالیت والد Fragment
Activity.findViewById()
را فراخوانی کنید. هنگام فراخوانی setAdapter()
از Context
فعالیت والد استفاده کنید. به عنوان مثال:
کاتلین
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 } }
جاوا
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
را پیاده سازی می کند، همانطور که در بخش Define a Fragment نشان داده شده است که لیست مخاطبین را نمایش می دهد .
برای ادامه راه اندازی شنونده، با فراخوانی متد setOnItemClickListener()
در onActivityCreated()
آن را به ListView
متصل کنید. به عنوان مثال:
کاتلین
fun onActivityCreated(savedInstanceState:Bundle) { ... // Set the item click listener to be the current fragment. contactsList.onItemClickListener = this ... }
جاوا
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
است.DISPLAY_NAME_PRIMARY ; در نسخههای قبلی، نام آن Contacts.DISPLAY_NAME
است.DISPLAY_NAME.
ستون Contacts._ID
توسط فرآیند اتصال SimpleCursorAdapter
استفاده می شود. Contacts._ID
و LOOKUP_KEY
با هم برای ایجاد یک URI محتوا برای مخاطبی که کاربر انتخاب می کند استفاده می شود.
کاتلین
... @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 )
جاوا
... @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
ثابتهایی تعریف کنید، زیرا ایندکسها با ترتیب نام ستونها در طرحبندی شما یکسان هستند. به عنوان مثال:
کاتلین
// 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
جاوا
// 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 را از بین می برد. به عنوان مثال:
کاتلین
// 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)
جاوا
// 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()
اکشن را برای شنونده اجرا کنید:
کاتلین
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. */ } }
جاوا
@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()
همانطور که در مثال زیر نشان داده شده است انجام دهید:
کاتلین
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)
جاوا
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 به کل جدول اشاره دارد، همانطور که در مثال زیر نشان داده شده است:
کاتلین
... 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() }
جاوا
... @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
با نتایج جستجو به روز می کند:
کاتلین
override fun onLoadFinished(loader: Loader<Cursor>, cursor: Cursor) { // Put the result Cursor in the adapter for the ListView cursorAdapter?.swapCursor(cursor) }
جاوا
@Override public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { // Put the result Cursor in the adapter for the ListView cursorAdapter.swapCursor(cursor); }
متد onLoaderReset()
زمانی فراخوانی میشود که چارچوب لودر تشخیص دهد که Cursor
نتیجه حاوی دادههای قدیمی است. مرجع SimpleCursorAdapter
را به Cursor
موجود حذف کنید. اگر این کار را نکنید، چارچوب لودر Cursor
را بازیافت نمی کند، که باعث نشت حافظه می شود. به عنوان مثال:
کاتلین
override fun onLoaderReset(loader: Loader<Cursor>) { // Delete the reference to the existing Cursor cursorAdapter?.swapCursor(null) }
جاوا
@Override public void onLoaderReset(Loader<Cursor> loader) { // Delete the reference to the existing Cursor cursorAdapter.swapCursor(null); }
اکنون بخشهای کلیدی یک برنامه را دارید که یک رشته جستجو را با نام مخاطبین مطابقت میدهد و نتیجه را در ListView
برمیگرداند. کاربر می تواند روی نام مخاطب کلیک کند تا آن را انتخاب کند. این یک شنونده را فعال می کند که در آن می توانید بیشتر با داده های مخاطب کار کنید. به عنوان مثال، می توانید جزئیات مخاطب را بازیابی کنید. برای یادگیری نحوه انجام این کار، با درس بعدی، بازیابی جزئیات برای یک مخاطب ، ادامه دهید.
برای کسب اطلاعات بیشتر در مورد رابط های کاربری جستجو، راهنمای API ایجاد رابط جستجو را بخوانید.
بخشهای باقیمانده در این درس راههای دیگری برای یافتن مخاطبین در ارائهدهنده مخاطبین را نشان میدهند.
مخاطب را با نوع خاصی از داده مطابقت دهید
این تکنیک به شما امکان می دهد نوع داده ای را که می خواهید مطابقت دهید مشخص کنید. بازیابی بر اساس نام نمونه خاصی از این نوع پرس و جو است، اما می توانید این کار را برای هر یک از انواع داده های جزئیات مرتبط با یک مخاطب نیز انجام دهید. به عنوان مثال، می توانید مخاطبینی را که کد پستی خاصی دارند، بازیابی کنید. در این مورد، رشته جستجو باید با داده های ذخیره شده در ردیف کد پستی مطابقت داشته باشد.
برای پیاده سازی این نوع بازیابی، ابتدا کد زیر را همانطور که در قسمت های قبلی ذکر شده است پیاده سازی کنید:
- درخواست اجازه برای خواندن ارائه دهنده.
- ListView و طرح بندی آیتم ها را تعریف کنید.
- قطعه ای را تعریف کنید که لیست مخاطبین را نمایش دهد.
- متغیرهای سراسری را تعریف کنید.
- Fragment را مقداردهی اولیه کنید.
- CursorAdapter را برای ListView تنظیم کنید.
- شنونده مخاطب انتخابی را تنظیم کنید.
- برای شاخص های ستون مکان نما، ثابت ها را تعریف کنید.
اگرچه دادهها را از جدول دیگری بازیابی میکنید، ترتیب ستونها در پروژکشن یکسان است، بنابراین میتوانید از همان شاخصها برای مکاننما استفاده کنید.
- متد onItemClick() را تعریف کنید.
- لودر را راه اندازی کنید.
- onLoadFinished() و onLoaderReset را پیاده سازی کنید.
مراحل زیر کد اضافی مورد نیاز برای تطبیق یک رشته جستجو با نوع خاصی از داده های جزئیات و نمایش نتایج را به شما نشان می دهد.
نوع داده و جدول را انتخاب کنید
برای جستجوی نوع خاصی از داده های جزئیات، باید مقدار نوع MIME سفارشی برای نوع داده را بدانید. هر نوع داده دارای یک مقدار نوع MIME منحصر به فرد است که توسط یک CONTENT_ITEM_TYPE
ثابت در زیر کلاس ContactsContract.CommonDataKinds
مرتبط با نوع داده تعریف شده است. زیر کلاس ها دارای نام هایی هستند که نوع داده آنها را نشان می دهد. برای مثال، کلاس فرعی برای دادههای ایمیل، ContactsContract.CommonDataKinds.Email
است و نوع MIME سفارشی برای دادههای ایمیل با ثابت Email.CONTENT_ITEM_TYPE
تعریف میشود.
برای جستجوی خود از جدول ContactsContract.Data
استفاده کنید. تمام ثابت هایی که برای طرح ریزی، بند انتخاب و ترتیب مرتب سازی نیاز دارید در این جدول تعریف شده یا به ارث برده می شوند.
فرافکنی را تعریف کنید
برای تعریف یک طرح، یک یا چند ستون تعریف شده در ContactsContract.Data
یا کلاس هایی که از آنها به ارث می رسد را انتخاب کنید. ارائه دهنده Contacts قبل از بازگرداندن ردیف ها، یک اتصال ضمنی بین ContactsContract.Data
و سایر جداول انجام می دهد. به عنوان مثال:
کاتلین
@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 )
جاوا
@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
است. با الحاق یک کاراکتر "'
" (تک نقل قول) به ابتدا و انتهای ثابت، مقدار را در گیومه های تکی قرار دهید. در غیر این صورت، ارائه دهنده مقدار را به عنوان یک نام متغیر به جای یک مقدار رشته تفسیر می کند. برای این مقدار نیازی به استفاده از نگهدارنده مکان ندارید، زیرا از یک مقدار ثابت به جای یک مقدار عرضه شده توسط کاربر استفاده می کنید.
به عنوان مثال:
کاتلین
/* * 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}'"
جاوا
/* * 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 + "'";
سپس، متغیرهایی را تعریف کنید که حاوی آرگومان انتخاب باشند:
کاتلین
private var searchString: String? = null private val selectionArgs: Array<String> = arrayOf("")
جاوا
String searchString; String[] selectionArgs = { "" };
پیاده سازی onCreateLoader()
اکنون که دادههای مورد نظر و نحوه یافتن آن را مشخص کردهاید، در پیادهسازی onCreateLoader()
کوئری تعریف کنید. یک CursorLoader
جدید را از این روش با استفاده از طرح ریزی، بیان متن انتخابی و آرایه انتخاب به عنوان آرگومان برگردانید. برای URI محتوا، از Data.CONTENT_URI
استفاده کنید. به عنوان مثال:
کاتلین
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() }
جاوا
@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" را برمی گرداند. همچنین مخاطبینی را که در «خیابان دو» زندگی میکنند برمیگرداند.
برای پیاده سازی این نوع بازیابی، ابتدا کد زیر را همانطور که در قسمت های قبلی ذکر شده است پیاده سازی کنید:
- درخواست اجازه برای خواندن ارائه دهنده.
- ListView و طرح بندی آیتم ها را تعریف کنید.
- قطعه ای را تعریف کنید که لیست مخاطبین را نمایش دهد.
- متغیرهای سراسری را تعریف کنید.
- Fragment را مقداردهی اولیه کنید.
- CursorAdapter را برای ListView تنظیم کنید.
- شنونده مخاطب انتخابی را تنظیم کنید.
- فرافکنی را تعریف کنید.
- برای شاخص های ستون مکان نما، ثابت ها را تعریف کنید.
برای این نوع بازیابی، از همان جدولی استفاده میکنید که در بخش تطبیق یک مخاطب با نام و فهرست کردن نتایج استفاده کردید. از همان شاخص های ستون نیز استفاده کنید.
- متد onItemClick() را تعریف کنید.
- لودر را راه اندازی کنید.
- onLoadFinished() و onLoaderReset را پیاده سازی کنید.
مراحل زیر کد اضافی مورد نیاز برای تطبیق یک رشته جستجو با هر نوع داده و نمایش نتایج را به شما نشان می دهد.
معیارهای انتخاب را حذف کنید
ثابت های SELECTION
یا متغیر mSelectionArgs
را تعریف نکنید. اینها در این نوع بازیابی استفاده نمی شوند.
پیاده سازی onCreateLoader()
متد onCreateLoader()
را پیاده سازی کنید و یک CursorLoader
جدید را برگردانید. شما نیازی به تبدیل رشته جستجو به یک الگو ندارید، زیرا ارائه دهنده مخاطبین این کار را به صورت خودکار انجام می دهد. از Contacts.CONTENT_FILTER_URI
به عنوان URI پایه استفاده کنید و رشته جستجوی خود را با فراخوانی Uri.withAppendedPath()
به آن اضافه کنید. استفاده از این URI به طور خودکار جستجو برای هر نوع داده را آغاز می کند، همانطور که در مثال زیر نشان داده شده است:
کاتلین
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() }
جاوا
@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 ); }
این قطعه کد اساس برنامه ای است که جستجوی گسترده ای در ارائه دهنده مخاطبین انجام می دهد. این تکنیک برای برنامههایی مفید است که میخواهند عملکردی مشابه صفحه فهرست مخاطبین برنامه People پیادهسازی کنند.