این درس نحوه بازیابی اطلاعات جزییات یک مخاطب مانند آدرس ایمیل، شماره تلفن و غیره را نشان می دهد. این جزئیاتی است که کاربران هنگام بازیابی یک مخاطب به دنبال آن هستند. می توانید تمام جزئیات یک مخاطب را به آنها بدهید یا فقط جزئیات یک نوع خاص مانند آدرس ایمیل را نمایش دهید.
مراحل این درس فرض می کند که شما از قبل یک ردیف ContactsContract.Contacts
برای مخاطبی که کاربر انتخاب کرده است دارید. درس بازیابی نام مخاطبین نحوه بازیابی لیستی از مخاطبین را نشان می دهد.
تمام جزئیات یک مخاطب را بازیابی کنید
برای بازیابی همه جزئیات یک مخاطب، جدول ContactsContract.Data
را برای هر ردیفی که حاوی LOOKUP_KEY
مخاطب است جستجو کنید. این ستون در جدول ContactsContract.Data
موجود است، زیرا ارائه دهنده Contacts یک اتصال ضمنی بین جدول ContactsContract.Contacts
و جدول ContactsContract.Data
ایجاد می کند. ستون LOOKUP_KEY
با جزئیات بیشتر در درس بازیابی نام مخاطبین توضیح داده شده است.
توجه: بازیابی تمام جزئیات برای یک مخاطب، عملکرد دستگاه را کاهش می دهد، زیرا باید تمام ستون های جدول ContactsContract.Data
را بازیابی کند. قبل از استفاده از این تکنیک تأثیر عملکرد را در نظر بگیرید.
درخواست مجوزها
برای خواندن از ارائه دهنده مخاطبین، برنامه شما باید مجوز READ_CONTACTS
داشته باشد. برای درخواست این مجوز، عنصر فرزند زیر <manifest>
را به فایل مانیفست خود اضافه کنید:
<uses-permission android:name="android.permission.READ_CONTACTS" />
یک پروجکشن تنظیم کنید
بسته به نوع داده ای که یک ردیف دارد، ممکن است فقط از چند یا چند ستون استفاده کند. علاوه بر این، داده ها بسته به نوع داده در ستون های مختلف قرار دارند. برای اطمینان از دریافت تمام ستونهای ممکن برای همه انواع دادههای ممکن، باید همه نام ستونها را به طرح خود اضافه کنید. اگر Cursor
نتیجه را به ListView
متصل می کنید، همیشه Data._ID
بازیابی کنید. در غیر این صورت، اتصال کار نخواهد کرد. همچنین Data.MIMETYPE
را بازیابی کنید تا بتوانید نوع داده هر ردیفی را که بازیابی می کنید شناسایی کنید. به عنوان مثال:
کاتلین
private val PROJECTION: Array<out String> = arrayOf( ContactsContract.Data._ID, ContactsContract.Data.MIMETYPE, ContactsContract.Data.DATA1, ContactsContract.Data.DATA2, ContactsContract.Data.DATA3, ContactsContract.Data.DATA4, ContactsContract.Data.DATA5, ContactsContract.Data.DATA6, ContactsContract.Data.DATA7, ContactsContract.Data.DATA8, ContactsContract.Data.DATA9, ContactsContract.Data.DATA10, ContactsContract.Data.DATA11, ContactsContract.Data.DATA12, ContactsContract.Data.DATA13, ContactsContract.Data.DATA14, ContactsContract.Data.DATA15 )
جاوا
private static final String[] PROJECTION = { ContactsContract.Data._ID, ContactsContract.Data.MIMETYPE, ContactsContract.Data.DATA1, ContactsContract.Data.DATA2, ContactsContract.Data.DATA3, ContactsContract.Data.DATA4, ContactsContract.Data.DATA5, ContactsContract.Data.DATA6, ContactsContract.Data.DATA7, ContactsContract.Data.DATA8, ContactsContract.Data.DATA9, ContactsContract.Data.DATA10, ContactsContract.Data.DATA11, ContactsContract.Data.DATA12, ContactsContract.Data.DATA13, ContactsContract.Data.DATA14, ContactsContract.Data.DATA15 };
این طرح همه ستون ها را برای یک ردیف در جدول ContactsContract.Data
با استفاده از نام ستون های تعریف شده در کلاس ContactsContract.Data
بازیابی می کند.
به صورت اختیاری، می توانید از هر ثابت ستون دیگری که در کلاس ContactsContract.Data
تعریف شده یا به ارث رسیده است استفاده کنید. با این حال، توجه داشته باشید که ستون های SYNC1
تا SYNC4
برای استفاده توسط آداپتورهای همگام سازی قرار دارند، بنابراین داده های آنها مفید نیست.
معیارهای انتخاب را مشخص کنید
یک ثابت برای عبارت انتخابی خود، یک آرایه برای نگهداری آرگومان های انتخابی و یک متغیر برای نگهداری مقدار انتخاب تعریف کنید. از ستون Contacts.LOOKUP_KEY
برای پیدا کردن مخاطب استفاده کنید. به عنوان مثال:
کاتلین
// Defines the selection clause private const val SELECTION: String = "${ContactsContract.Data.LOOKUP_KEY} = ?" ... // Defines the array to hold the search criteria private val selectionArgs: Array<String> = arrayOf("") /* * Defines a variable to contain the selection value. Once you * have the Cursor from the Contacts table, and you've selected * the desired row, move the row's LOOKUP_KEY value into this * variable. */ private var lookupKey: String? = null
جاوا
// Defines the selection clause private static final String SELECTION = Data.LOOKUP_KEY + " = ?"; // Defines the array to hold the search criteria private String[] selectionArgs = { "" }; /* * Defines a variable to contain the selection value. Once you * have the Cursor from the Contacts table, and you've selected * the desired row, move the row's LOOKUP_KEY value into this * variable. */ private lateinit var lookupKey: String
با استفاده از "?" به عنوان یک مکان نگهدار در عبارت متن انتخابی شما تضمین می کند که جستجوی حاصل از طریق اتصال به جای کامپایل SQL ایجاد می شود. این رویکرد امکان تزریق مخرب SQL را از بین می برد.
ترتیب مرتب سازی را تعریف کنید
ترتیب مرتب سازی مورد نظر خود را در Cursor
به دست آمده تعریف کنید. برای نگه داشتن تمام ردیفهای یک نوع داده خاص، بر اساس Data.MIMETYPE
مرتب کنید. این آرگومان پرس و جو همه ردیف های ایمیل، همه ردیف های تلفن را با هم و غیره گروه بندی می کند. به عنوان مثال:
کاتلین
/* * Defines a string that specifies a sort order of MIME type */ private const val SORT_ORDER = ContactsContract.Data.MIMETYPE
جاوا
/* * Defines a string that specifies a sort order of MIME type */ private static final String SORT_ORDER = ContactsContract.Data.MIMETYPE;
توجه: برخی از انواع داده ها از یک نوع فرعی استفاده نمی کنند، بنابراین نمی توانید بر اساس نوع فرعی مرتب کنید. درعوض، باید از طریق Cursor
برگشتی تکرار کنید، نوع داده ردیف فعلی را تعیین کنید و دادهها را برای ردیفهایی که از یک نوع فرعی استفاده میکنند ذخیره کنید. پس از پایان خواندن مکان نما، می توانید هر نوع داده را بر اساس نوع فرعی مرتب کنید و نتایج را نمایش دهید.
Loader را مقداردهی اولیه کنید
همیشه از ارائه دهنده مخاطبین (و سایر ارائه دهندگان محتوا) در یک رشته پس زمینه بازیابی کنید. از چارچوب Loader تعریف شده توسط کلاس LoaderManager
و رابط LoaderManager.LoaderCallbacks
برای انجام بازیابی پس زمینه استفاده کنید.
هنگامی که آماده بازیابی ردیف ها هستید، با فراخوانی initLoader()
چارچوب لودر را مقداردهی اولیه کنید. یک شناسه عدد صحیح را به متد ارسال کنید. این شناسه به روش های LoaderManager.LoaderCallbacks
ارسال می شود. شناسه به شما کمک می کند تا از چندین بارگذار در یک برنامه استفاده کنید و به شما امکان می دهد بین آنها تفاوت قائل شوید.
قطعه زیر نحوه اولیه سازی چارچوب لودر را نشان می دهد:
کاتلین
// Defines a constant that identifies the loader private const val DETAILS_QUERY_ID: Int = 0 class DetailsFragment : Fragment(), LoaderManager.LoaderCallbacks<Cursor> { ... override fun onCreate(savedInstanceState: Bundle?) { ... // Initializes the loader framework loaderManager.initLoader(DETAILS_QUERY_ID, null, this)
جاوا
public class DetailsFragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor> { ... // Defines a constant that identifies the loader static int DETAILS_QUERY_ID = 0; ... @Override public void onCreate(Bundle savedInstanceState) { ... // Initializes the loader framework getLoaderManager().initLoader(DETAILS_QUERY_ID, null, this);
پیاده سازی onCreateLoader()
متد onCreateLoader()
را پیاده سازی کنید که بلافاصله پس از فراخوانی initLoader()
توسط فریم ورک لودر فراخوانی می شود. یک CursorLoader
از این روش برگردانید. از آنجایی که در حال جستجوی جدول ContactsContract.Data
هستید، Data.CONTENT_URI
ثابت به عنوان URI محتوا استفاده کنید. به عنوان مثال:
کاتلین
override fun onCreateLoader(loaderId: Int, args: Bundle?): Loader<Cursor> { // Choose the proper action mLoader = when(loaderId) { DETAILS_QUERY_ID -> { // Assigns the selection parameter selectionArgs[0] = lookupKey // Starts the query activity?.let { CursorLoader( it, ContactsContract.Data.CONTENT_URI, PROJECTION, SELECTION, selectionArgs, SORT_ORDER ) } } ... } return mLoader }
جاوا
@Override public Loader<Cursor> onCreateLoader(int loaderId, Bundle args) { // Choose the proper action switch (loaderId) { case DETAILS_QUERY_ID: // Assigns the selection parameter selectionArgs[0] = lookupKey; // Starts the query CursorLoader mLoader = new CursorLoader( getActivity(), ContactsContract.Data.CONTENT_URI, PROJECTION, SELECTION, selectionArgs, SORT_ORDER ); }
پیاده سازی onLoadFinished() و onLoaderReset()
متد onLoadFinished()
را پیاده سازی کنید. فریم ورک لودر onLoadFinished()
زمانی فراخوانی میکند که ارائهدهنده تماسها نتایج پرس و جو را برمیگرداند. به عنوان مثال:
کاتلین
override fun onLoadFinished(loader: Loader<Cursor>, data: Cursor) { when(loader.id) { DETAILS_QUERY_ID -> { /* * Process the resulting Cursor here. */ } ... } }
جاوا
@Override public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { switch (loader.getId()) { case DETAILS_QUERY_ID: /* * Process the resulting Cursor here. */ } break; ... } }
متد onLoaderReset()
زمانی فراخوانی میشود که چارچوب لودر تشخیص دهد که دادههای پشتیبان Cursor
نتیجه تغییر کرده است. در این مرحله، هرگونه ارجاع موجود به Cursor
با قرار دادن null حذف کنید. اگر این کار را نکنید، چارچوب لودر Cursor
قدیمی را از بین نمی برد و با نشت حافظه مواجه خواهید شد. به عنوان مثال:
کاتلین
override fun onLoaderReset(loader: Loader<Cursor>) { when (loader.id) { DETAILS_QUERY_ID -> { /* * If you have current references to the Cursor, * remove them here. */ } ... } }
جاوا
@Override public void onLoaderReset(Loader<Cursor> loader) { switch (loader.getId()) { case DETAILS_QUERY_ID: /* * If you have current references to the Cursor, * remove them here. */ } break; }
جزئیات خاص یک مخاطب را بازیابی کنید
بازیابی یک نوع داده خاص برای یک مخاطب، مانند همه ایمیل ها، از همان الگوی بازیابی همه جزئیات پیروی می کند. اینها تنها تغییراتی هستند که باید در کد فهرست شده در بازیابی همه جزئیات برای یک مخاطب ایجاد کنید:
- فرافکنی
- طرح خود را برای بازیابی ستون هایی که مختص نوع داده هستند، تغییر دهید. همچنین پروجکشن را تغییر دهید تا از ثابت های نام ستون تعریف شده در زیر کلاس
ContactsContract.CommonDataKinds
مربوط به نوع داده استفاده کند. - انتخاب
- متن انتخابی را برای جستجوی مقدار
MIMETYPE
که مخصوص نوع داده شما است، تغییر دهید. - ترتیب مرتب سازی
- از آنجایی که فقط یک نوع جزئیات را انتخاب میکنید،
Cursor
بازگشتی را براساسData.MIMETYPE
گروهبندی نکنید.
این تغییرات در بخش های زیر توضیح داده شده است.
فرافکنی را تعریف کنید
ستون هایی را که می خواهید بازیابی کنید، با استفاده از ثابت های نام ستون در زیر کلاس ContactsContract.CommonDataKinds
برای نوع داده تعریف کنید. اگر قصد دارید Cursor
خود را به ListView
متصل کنید، حتماً ستون _ID
را بازیابی کنید. به عنوان مثال، برای بازیابی اطلاعات ایمیل، طرح زیر را تعریف کنید:
کاتلین
private val PROJECTION: Array<String> = arrayOf( ContactsContract.CommonDataKinds.Email._ID, ContactsContract.CommonDataKinds.Email.ADDRESS, ContactsContract.CommonDataKinds.Email.TYPE, ContactsContract.CommonDataKinds.Email.LABEL )
جاوا
private static final String[] PROJECTION = { ContactsContract.CommonDataKinds.Email._ID, ContactsContract.CommonDataKinds.Email.ADDRESS, ContactsContract.CommonDataKinds.Email.TYPE, ContactsContract.CommonDataKinds.Email.LABEL };
توجه داشته باشید که این طرح از نام ستون های تعریف شده در کلاس ContactsContract.CommonDataKinds.Email
به جای نام ستون های تعریف شده در کلاس ContactsContract.Data
استفاده می کند. استفاده از نام ستون های خاص ایمیل، کد را خواناتر می کند.
در طرح ریزی، می توانید از هر یک از ستون های دیگر تعریف شده در زیر کلاس ContactsContract.CommonDataKinds
نیز استفاده کنید.
معیارهای انتخاب را تعریف کنید
یک عبارت متن جستجو را تعریف کنید که ردیفهایی را برای LOOKUP_KEY
یک مخاطب خاص و Data.MIMETYPE
جزئیات مورد نظر شما بازیابی میکند. مقدار MIMETYPE
را با الحاق یک کاراکتر " '
" (تک نقل قول) به ابتدا و انتهای ثابت در گیومه های تکی قرار دهید. در غیر این صورت، ارائه دهنده ثابت را به عنوان یک نام متغیر به جای یک مقدار رشته تفسیر می کند. برای این مقدار نیازی به استفاده از نگهدارنده مکان ندارید، زیرا از یک مقدار ثابت به جای یک مقدار عرضه شده توسط کاربر استفاده می کنید. به عنوان مثال:
کاتلین
/* * Defines the selection clause. Search for a lookup key * and the Email MIME type */ private const val SELECTION = "${ContactsContract.Data.LOOKUP_KEY} = ? AND " + "${ContactsContract.Data.MIMETYPE} = '${Email.CONTENT_ITEM_TYPE}'" ... // Defines the array to hold the search criteria private val selectionArgs: Array<String> = arrayOf("")
جاوا
/* * Defines the selection clause. Search for a lookup key * and the Email MIME type */ private static final String SELECTION = Data.LOOKUP_KEY + " = ?" + " AND " + Data.MIMETYPE + " = " + "'" + Email.CONTENT_ITEM_TYPE + "'"; // Defines the array to hold the search criteria private String[] selectionArgs = { "" };
ترتیب مرتب سازی را تعریف کنید
یک ترتیب مرتب سازی برای Cursor
برگشتی تعریف کنید. از آنجایی که در حال بازیابی یک نوع داده خاص هستید، مرتب سازی در MIMETYPE
را حذف کنید. در عوض، اگر نوع دادههای جزییاتی که جستجو میکنید شامل یک نوع فرعی است، آن را مرتب کنید. به عنوان مثال، برای داده های ایمیل می توانید بر اساس Email.TYPE
مرتب کنید:
کاتلین
private const val SORT_ORDER: String = "${Email.TYPE} ASC"
جاوا
private static final String SORT_ORDER = Email.TYPE + " ASC ";