Kişiler listesini alma

Bu derste, verileri bir arama dizesinin tamamı veya bir kısmıyla eşleşen kişilerin listesini aşağıdaki teknikler kullanarak nasıl alacağınız gösterilmektedir:

Kişi adlarını eşleştir
Arama dizesini kişi adı verilerinin tamamıyla veya bir kısmıyla eşleştirerek kişilerin listesini alın. Kişi Sağlayıcı, aynı adın birden fazla örneğine izin verdiğinden bu teknik, eşleşmelerin listesini döndürebilir.
Belirli bir veri türüyle (ör. telefon numarası) eşleşme
Arama dizesini e-posta adresi gibi belirli bir ayrıntı veri türüyle eşleştirerek kişilerin listesini alın. Örneğin, bu teknik, e-posta adresleri arama dizesiyle eşleşen tüm kişileri listelemenize olanak tanır.
Her tür veriyle eşleştirme
Arama dizesini ad, telefon numarası, açık adres, e-posta adresi vb. herhangi bir ayrıntı verisiyle eşleştirerek kişilerin listesini alın. Örneğin, bu teknik bir arama dizesi için her tür veriyi kabul etmenize ve ardından verilerin dizeyle eşleştiği kişileri listelemenize olanak tanır.

Not: Bu dersteki tüm örneklerde, Kişiler Sağlayıcı'dan veri almak için bir CursorLoader kullanılmıştır. CursorLoader, sorgusunu kullanıcı arayüzü iş parçacığından ayrı bir iş parçacığında çalıştırır. Bu, sorgunun kullanıcı arayüzü yanıt sürelerini yavaşlatmasını ve kötü bir kullanıcı deneyimine neden olmamasını sağlar. Daha fazla bilgi için Arka Planda Veri Yükleme konulu Android eğitim sınıfına bakın.

Sağlayıcıyı okuma izni iste

Kişi Sağlayıcı'da herhangi bir türde arama yapabilmeniz için uygulamanızın READ_CONTACTS iznine sahip olması gerekir. Bunu istemek için bu <uses-permission> öğesini, manifest dosyanıza <manifest> öğesinin alt öğesi olarak ekleyin:

    <uses-permission android:name="android.permission.READ_CONTACTS" />

Bir kişiyi ada göre eşleştirin ve sonuçları listeleyin

Bu teknik, bir arama dizesini Kişi Sağlayıcının ContactsContract.Contacts tablosundaki bir kişinin veya kişilerin adıyla eşleştirmeye çalışır. Kullanıcının eşleşen kişiler arasından seçim yapmasına olanak tanımak için genellikle sonuçları bir ListView içinde görüntülemek istersiniz.

ListView ve öğe düzenlerini tanımlama

Arama sonuçlarını bir ListView içinde görüntülemek için ListView dahil tüm kullanıcı arayüzünü tanımlayan bir ana düzen dosyasına ve bir ListView satırını tanımlayan bir öğe düzen dosyasına ihtiyacınız vardır. Örneğin, aşağıdaki XML ile res/layout/contacts_list_view.xml ana düzen dosyasını oluşturabilirsiniz:

<?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"/>

Bu XML, yerleşik Android ListView widget'ını android:id/list kullanır.

Aşağıdaki XML ile contacts_list_item.xml öğe düzen dosyasını tanımlayın:

<?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"/>

Bu XML, yerleşik Android TextView widget'ını android:text1 kullanır.

Not: Dizeyi dolaylı olarak almak isteyebileceğinizden bu derste kullanıcıdan arama dizesi almayla ilgili kullanıcı arayüzü ele alınmamaktadır. Örneğin, kullanıcıya, gelen kısa mesajdaki bir dizeyle eşleşen kişileri arama seçeneği sunabilirsiniz.

Yazdığınız iki düzen dosyası, ListView gösteren bir kullanıcı arayüzü tanımlar. Bir sonraki adım, kişilerin listesini görüntülemek için bu kullanıcı arayüzünü kullanan bir kod yazmaktır.

Kişi listesini görüntüleyen bir Parça tanımlayın

Kişiler listesini görüntülemek için Activity tarafından yüklenen bir Fragment tanımlayarak başlayın. Fragment kullanımı daha esnek bir tekniktir. Çünkü listeyi görüntülemek için bir Fragment ve kullanıcının listeden seçtiği bir kişinin ayrıntılarını görüntülemek için ikinci bir Fragment kullanabilirsiniz. Bu yaklaşımı kullanarak bu derste sunulan tekniklerden birini, Bir kişinin ayrıntılarını alma dersindeki bir teknikle birleştirebilirsiniz.

Activity öğesinden bir veya daha fazla Fragment nesnesini nasıl kullanacağınızı öğrenmek için Fragments ile dinamik kullanıcı arayüzü oluşturma adlı eğitim sınıfını okuyun.

Android çerçevesi, Kişi Sağlayıcıya karşı sorgu yazmanıza yardımcı olmak için ContactsContract adlı bir sözleşme sınıfı sağlar. Bu sınıf, sağlayıcıya erişmek için faydalı sabit değerleri ve yöntemleri tanımlar. Bu sınıfı kullandığınızda içerik URI'leri, tablo adları veya sütunlar için kendi sabit değerlerinizi tanımlamanız gerekmez. Bu sınıfı kullanmak için aşağıdaki ifadeyi ekleyin:

Kotlin

import android.provider.ContactsContract

Java

import android.provider.ContactsContract;

Kod, sağlayıcıdan veri almak için CursorLoader kullandığından, LoaderManager.LoaderCallbacks yükleyici arayüzünü uyguladığını belirtmeniz gerekir. Ayrıca, kullanıcının arama sonuçları listesinden hangi kişiyi seçtiğini tespit etmeye yardımcı olması için AdapterView.OnItemClickListener bağdaştırıcı arayüzünü uygulayın. Örnek:

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 {

Genel değişkenleri tanımlama

Kodun diğer bölümlerinde kullanılan genel değişkenleri tanımlayın:

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;
    ...

Not: Contacts.DISPLAY_NAME_PRIMARY, Android 3.0 (API sürümü 11) veya sonraki sürümleri gerektirdiğinden, uygulamanızın minSdkVersion değerini 10 veya daha düşük bir değere ayarlamak Android Studio'da Android Lint uyarısı oluşturur. Bu uyarıyı devre dışı bırakmak için @SuppressLint("InlinedApi") ek açıklamasını FROM_COLUMNS tanımından önce ekleyin.

Parçayı İlk Kullanıma Hazırlama

Fragment öğesini başlatın. Android sisteminin gerektirdiği boş, herkese açık kurucuyu ekleyin ve onCreateView() geri çağırma yöntemini kullanarak Fragment nesnesinin kullanıcı arayüzünü şişirin. Örnek:

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 için CursorAdapter'ı ayarlama

Arama sonuçlarını ListView öğesine bağlayan SimpleCursorAdapter öğesini ayarlayın. Kişileri görüntüleyen ListView nesnesini almak için Fragment öğesinin üst etkinliğini kullanarak Activity.findViewById() yöntemini çağırmanız gerekir. setAdapter() çağırırken ebeveyn etkinliğinin Context özelliğini kullanın. Örnek:

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);
    }

Seçilen kişi dinleyicisini ayarlayın

Bir aramanın sonuçlarını görüntülediğinizde, genellikle kullanıcının daha sonra işlenmek üzere tek bir kişi seçmesine izin vermek istersiniz. Örneğin, kullanıcı bir kişiyi tıkladığında bu kişinin adresini harita üzerinde görüntüleyebilirsiniz. Bu özelliği sağlamak için Kişiler listesini gösteren bir Parça tanımlama bölümünde gösterildiği gibi önce, sınıfın AdapterView.OnItemClickListener yöntemini uyguladığını belirterek geçerli Fragment özelliğini tıklama işleyici olarak tanımladınız.

İşleyiciyi ayarlamaya devam etmek için onActivityCreated() içinde setOnItemClickListener() yöntemini çağırarak ListView'a bağlayın. Örnek:

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);
        ...
    }

Mevcut Fragment öğesinin ListView için OnItemClickListener olduğunu belirttiğinizden, tıklama etkinliğini işleyen gerekli onItemClick() yöntemini uygulamanız gerekiyor. Bu, daha sonraki bir bölümde açıklanmıştır.

Projeksiyon tanımlama

Sorgunuzdan döndürmek istediğiniz sütunları içeren bir sabit değer tanımlayın. ListView içindeki her öğe, kişinin adının ana biçimini içeren görünen adını gösterir. Android 3.0 (API sürümü 11) ve sonraki sürümlerde bu sütunun adı Contacts.DISPLAY_NAME_PRIMARY, ondan önceki sürümlerde ise Contacts.DISPLAY_NAME şeklindedir.

Contacts._ID sütunu, SimpleCursorAdapter bağlama işlemi tarafından kullanılır. Kullanıcının seçtiği kişi için bir içerik URI'sı oluşturmak amacıyla Contacts._ID ve LOOKUP_KEY birlikte kullanılır.

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

        };

İmleç sütunu dizinleri için sabit değerler tanımlama

Bir Cursor öğesindeki tek bir sütundan veri almak için sütunun dizininin Cursor içinde olması gerekir. Dizinler, projeksiyonunuzdaki sütun adlarının sıralamasıyla aynı olduğundan Cursor sütunlarının dizinleri için sabit değerler tanımlayabilirsiniz. Örnek:

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;

Seçim ölçütlerini belirleme

İstediğiniz verileri belirtmek için sağlayıcıya aranacak veri sütunları ile bulunacak değerleri bildiren metin ifadeleri ve değişkenlerin bir kombinasyonunu oluşturun.

Metin ifadesi için arama sütunlarını listeleyen bir sabit değer tanımlayın. Bu ifade, değerleri de içerebilir ancak tercih edilen uygulama, değerlerin "?" yer tutucusuyla temsil edilmesidir. Alma işlemi sırasında, yer tutucu bir diziden gelen değerlerle değiştirilir. Yer tutucu olarak "?" kullanılması, arama spesifikasyonunun SQL derlemesi yerine bağlama ile oluşturulmasını sağlar. Bu uygulama, kötü amaçlı SQL yerleştirme olasılığını ortadan kaldırır. Örnek:

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() yöntemini tanımlayın

Önceki bir bölümde, ListView için öğe tıklama işleyiciyi ayarladınız. Şimdi AdapterView.OnItemClickListener.onItemClick() yöntemini tanımlayarak işlemi işleyici için uygulayın:

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.
         */
    }

Yükleyiciyi başlatın

Veri almak için CursorLoader kullandığınızdan, arka plan iş parçacığını ve eşzamansız almayı kontrol eden diğer değişkenleri başlatmanız gerekir. Başlatma işlemini aşağıdaki örnekte gösterildiği gibi onCreate() içinde yapın:

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() işlevini uygulama

initLoader() yöntemini çağırdıktan hemen sonra yükleyici çerçevesi tarafından çağrılan onCreateLoader() yöntemini uygulayın.

onCreateLoader() sayfasında arama dizesi kalıbını ayarlayın. Bir dizeyi bir kalıba dönüştürmek için, sıfır veya daha fazla karakterden oluşan bir diziyi temsil etmek üzere "%" (yüzde) karakterlerini veya tek bir karakteri temsil etmek için "_" (alt çizgi) karakterini ya da her ikisini birden ekleyin. Örneğin, "%Jefferson%" kalıbı hem "Thomas Cemerson" hem de "Jefferson Davis" ile eşleşir.

Yöntemden yeni bir CursorLoader döndürün. İçerik URI'si için Contacts.CONTENT_URI kullanın. Bu URI, aşağıdaki örnekte gösterildiği gibi, tablonun tamamını ifade eder:

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() ve onLoaderReset() uygulamalarını uygulayın

onLoadFinished() yöntemini uygulayın. Kişi Sağlayıcısı sorgunun sonuçlarını döndürdüğünde yükleyici çerçevesi onLoadFinished() işlevini çağırır. Bu yöntemde, Cursor sonucunu SimpleCursorAdapter içine yerleştirin. Bu işlem, ListView öğesini arama sonuçlarıyla otomatik olarak günceller:

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);
    }

Yükleyici çerçevesi, Cursor sonucunun eski veri içerdiğini algıladığında onLoaderReset() yöntemi çağrılır. Mevcut Cursor öğesine ait SimpleCursorAdapter referansını silin. Bunu yapmazsanız yükleyici çerçevesi, Cursor öğesini geri dönüştürmez ve bu da bellek sızıntısına neden olur. Örnek:

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);

    }

Artık bir arama dizesini kişi adlarıyla eşleştiren ve sonucu ListView ile döndüren bir uygulamanın önemli parçalarına sahipsiniz. Kullanıcı, kişi adını tıklayarak seçebilir. Bu, kişinin verileriyle daha ayrıntılı bir şekilde çalışabileceğiniz bir işleyiciyi tetikler. Örneğin, kişinin bilgilerini alabilirsiniz. Bunu nasıl yapacağınızı öğrenmek için sonraki ders olan Kişinin ayrıntılarını alma ile devam edin.

Arama kullanıcı arayüzleri hakkında daha fazla bilgi edinmek için Arama arayüzü oluşturma API kılavuzunu okuyun.

Bu dersin geri kalan bölümlerinde Kişi Sağlayıcı'da kişileri bulmanın diğer yolları gösterilmektedir.

Bir kişiyi belirli bir veri türüne göre eşleştirme

Bu teknik, eşleştirmek istediğiniz veri türünü belirtmenize olanak tanır. Ada göre alma, bu tür bir sorguya özel bir örnektir ancak bunu bir kişiyle ilişkili herhangi bir ayrıntı verisi türü için de yapabilirsiniz. Örneğin, belirli bir posta koduna sahip kişileri alabilirsiniz. Bu durumda, arama dizesinin posta kodu satırında depolanan verilerle eşleşmesi gerekir.

Bu tür bir alma işlemi uygulamak için önce önceki bölümlerde listelendiği gibi aşağıdaki kodu uygulayın:

  • Sağlayıcıyı Okuma İzni İsteyin.
  • ListView ve öğe düzenlerini tanımlayın.
  • Kişi listesini görüntüleyen bir Parça tanımlayın.
  • Genel değişkenleri tanımlama.
  • Parçayı başlatın.
  • ListView için CursorAdapter'ı ayarlayın.
  • Seçilen kişi dinleyiciyi ayarlayın.
  • İmleç sütunu dizinleri için sabit değerler tanımlayın.

    Farklı bir tablodan veri almanıza rağmen projeksiyondaki sütunların sırası aynıdır. Bu nedenle, İmleç için aynı dizinleri kullanabilirsiniz.

  • onItemClick() yöntemini tanımlayın.
  • Yükleyiciyi başlatın.
  • onLoadFinished() ve onLoaderReset() uygulayın.

Aşağıdaki adımlar, bir arama dizesini belirli bir ayrıntı veri türüyle eşleştirmek ve sonuçları görüntülemek için ihtiyacınız olan ek kodu gösterir.

Veri türünü ve tabloyu seçin

Belirli bir ayrıntı veri türünü aramak için veri türüne ait özel MIME türü değerini bilmeniz gerekir. Her veri türü, veri türüyle ilişkili ContactsContract.CommonDataKinds alt sınıfındaki sabit bir CONTENT_ITEM_TYPE ile tanımlanan benzersiz bir MIME türü değerine sahiptir. Alt sınıfların adları, veri türlerini belirten adlara sahiptir. Örneğin, e-posta verileri için alt sınıf ContactsContract.CommonDataKinds.Email, e-posta verileri için özel MIME türü ise sabit Email.CONTENT_ITEM_TYPE ile tanımlanır.

Aramanızda ContactsContract.Data tablosunu kullanın. Projeksiyonunuz, seçim ifadeniz ve sıralama şekliniz için ihtiyacınız olan tüm sabit değerler, bu tabloda tanımlanır veya bu tablo tarafından devralınır.

Projeksiyon tanımlama

Bir projeksiyon tanımlamak için ContactsContract.Data özelliğinde ya da devraldığı sınıflarda tanımlanan bir veya daha fazla sütunu seçin. Kişi Sağlayıcısı, satırları döndürmeden önce ContactsContract.Data ile diğer tablolar arasında örtülü bir birleştirme yapar. Örnek:

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
        };

Arama ölçütlerini tanımlayın

Belirli bir veri türünde dize aramak için aşağıdakilerden bir seçim ifadesi oluşturun:

  • Arama dizenizi içeren sütunun adı. Bu ad veri türüne göre değişir. Bu nedenle, veri türüne karşılık gelen ContactsContract.CommonDataKinds alt sınıfını bulmanız ve ardından bu alt sınıftan sütun adını seçmeniz gerekir. Örneğin, e-posta adreslerini aramak için Email.ADDRESS sütununu kullanın.
  • Arama dizesinin kendisi (seçim yan tümcesinde "?" karakteriyle gösterilir).
  • Özel MIME türü değerini içeren sütunun adı. Bu ad her zaman Data.MIMETYPE şeklindedir.
  • Veri türü için özel MIME türü değeri. Daha önce açıklandığı gibi bu, ContactsContract.CommonDataKinds alt sınıfındaki CONTENT_ITEM_TYPE sabittir. Örneğin, e-posta verileri için MIME türü değeri Email.CONTENT_ITEM_TYPE şeklindedir. Bir "'" (tek tırnak) karakterini sabit değerin başlangıcında ve sonunda birleştirerek değeri tek tırnak içine alın. Aksi takdirde sağlayıcı, değeri dize değeri yerine değişken adı olarak yorumlar. Kullanıcı tarafından sağlanan değer yerine sabit bir değer kullandığınızdan bu değer için yer tutucu kullanmanız gerekmez.

Örnek:

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 + "'";

Ardından, seçim bağımsız değişkenini içerecek değişkenleri tanımlayın:

Kotlin

    private var searchString: String? = null
    private val selectionArgs: Array<String> = arrayOf("")

Java

    String searchString;
    String[] selectionArgs = { "" };

onCreateLoader() işlevini uygulama

İstediğiniz verileri ve bu verileri nasıl bulacağınızı belirttiğinize göre onCreateLoader() uygulamanızda bir sorgu tanımlayın. Projeksiyonunuzu, seçim metni ifadenizi ve seçim dizinizi bağımsız değişken olarak kullanarak bu yöntemden yeni bir CursorLoader döndürün. İçerik URI'si için Data.CONTENT_URI kullanın. Örnek:

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
        );
    }

Bu kod snippet'leri, belirli bir ayrıntı veri türüne dayalı basit bir ters aramanın temelini oluşturur. Bu, uygulamanız e-postalar gibi belirli bir veri türüne odaklanıyorsa ve kullanıcıların bir veri parçasıyla ilişkilendirilen adları almalarına izin vermek istiyorsanız kullanılacak en iyi tekniktir.

Bir kişiyi herhangi bir veri türüne göre eşleştirme

Herhangi bir veri türüne dayalı olarak bir kişi alınması; ad, e-posta adresi, posta adresi, telefon numarası gibi verilerden herhangi biri arama dizesiyle eşleşiyorsa kişileri döndürür. Bunun sonucunda çok sayıda arama sonucu elde edilir. Örneğin, arama dizesi "Doğan" ise herhangi bir veri türü için yapılan arama "Can Doğru" kişisini döndürür; "Doğan Sokak"ta yaşayan kişileri de döndürür.

Bu tür bir alma işlemi uygulamak için önce önceki bölümlerde listelendiği gibi aşağıdaki kodu uygulayın:

  • Sağlayıcıyı Okuma İzni İsteyin.
  • ListView ve öğe düzenlerini tanımlayın.
  • Kişi listesini görüntüleyen bir Parça tanımlayın.
  • Genel değişkenleri tanımlama.
  • Parçayı başlatın.
  • ListView için CursorAdapter'ı ayarlayın.
  • Seçilen kişi dinleyiciyi ayarlayın.
  • Projeksiyon tanımlama.
  • İmleç sütunu dizinleri için sabit değerler tanımlayın.

    Bu tür alma işlemleri için Bir kişiyi ada göre eşleştirme ve sonuçları listeleme bölümünde kullandığınız tabloyu kullanırsınız. Aynı sütun dizinlerini de kullanın.

  • onItemClick() yöntemini tanımlayın.
  • Yükleyiciyi başlatın.
  • onLoadFinished() ve onLoaderReset() uygulayın.

Aşağıdaki adımlar bir arama dizesini herhangi bir veri türüyle eşleştirmek ve sonuçları görüntülemek için ihtiyacınız olan ek kodu gösterir.

Seçim ölçütlerini kaldır

SELECTION sabitlerini veya mSelectionArgs değişkenini tanımlamayın. Bunlar, bu tür alma işleminde kullanılmaz.

onCreateLoader() işlevini uygulama

Yeni bir CursorLoader döndürerek onCreateLoader() yöntemini uygulayın. Kişi Sağlayıcısı bunu otomatik olarak yaptığından, arama dizesini bir kalıba dönüştürmenize gerek yoktur. Temel URI olarak Contacts.CONTENT_FILTER_URI kullanın ve Uri.withAppendedPath() yöntemini çağırarak arama dizenizi buna ekleyin. Bu URI'nın kullanılması, aşağıdaki örnekte gösterildiği gibi otomatik olarak herhangi bir veri türünü aramayı tetikler:

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
        );
    }

Bu kod snippet'leri, Kişi Sağlayıcı'da kapsamlı bir arama yapan bir uygulamanın temelini oluşturur. Bu teknik, Kişiler uygulamasının kişi listesi ekranına benzer işlevler uygulamak isteyen uygulamalar için yararlıdır.