Yükleyiciler

Yükleyiciler, Android 9 (API düzeyi 28) itibarıyla kullanımdan kaldırılmıştır. Activity ve Fragment yaşam döngülerini işlerken veri yüklemeyle ilgilenmek için önerilen seçenek, ViewModel nesneleri ve LiveData öğelerinin bir kombinasyonunu kullanmaktır. Görünüm modelleri, yükleyiciler gibi yapılandırma değişikliklerinden ancak daha az ortak kodla varlığını korur. LiveData, birden çok görünüm modelinde yeniden kullanabileceğiniz, yaşam döngüsüne duyarlı bir veri yükleme yöntemi sağlar. MediatorLiveData kullanarak LiveData öğesini de birleştirebilirsiniz. Verilerdeki değişiklikleri gözlemlemek için Oda veritabanındaki sorgular gibi gözlemlenebilir tüm sorgular kullanılabilir.

ViewModel ve LiveData özellikleri, Service gibi LoaderManager ürününe erişiminizin olmadığı durumlarda da kullanılabilir. Bu ikisini birlikte kullanmak, kullanıcı arayüzü yaşam döngüsüyle uğraşmak zorunda kalmadan uygulamanızın ihtiyaç duyduğu verilere kolayca erişmenizi sağlar. LiveData hakkında daha fazla bilgi edinmek için LiveData'e genel bakış sayfasını inceleyin. ViewModel hakkında daha fazla bilgi edinmek için ViewModel'e genel bakış sayfasını inceleyin.

Yükleyici API'si, bir içerik sağlayıcıdan ya da başka bir veri kaynağından, FragmentActivity veya Fragment içinde görüntülenmek üzere veri yüklemenize olanak tanır.

Yükleyiciler olmadığında karşılaşabileceğiniz bazı sorunlar şunlardır:

  • Verileri doğrudan etkinlik veya parçada getirirseniz kullanıcılarınız, kullanıcı arayüzü iş parçacığından yavaş olabilecek sorgular gerçekleştirdikleri için yanıt vermeme sorunu yaşar.
  • Verileri başka bir iş parçacığından (örneğin, AsyncTask ile) getirirseniz onDestroy() ve yapılandırma değişiklikleri gibi çeşitli etkinlikler veya parça yaşam döngüsü etkinlikleri aracılığıyla hem bu iş parçacığını hem de kullanıcı arayüzü iş parçacığını yönetmekten siz sorumlu olursunuz.

Yükleyiciler bu sorunları çözer ve başka avantajlar da sunar:

  • Yükleyiciler, kullanıcı arayüzünün yavaş veya duyarsız olmasını önlemek için ayrı iş parçacıkları üzerinde çalışır.
  • Yükleyiciler, etkinlikler gerçekleştiğinde geri çağırma yöntemleri sağlayarak iş parçacığı yönetimini basitleştirir.
  • Yükleyiciler, yinelenen sorguları önlemek için yapılandırma değişikliklerinde kalır ve sonuçları önbelleğe alır.
  • Yükleyiciler, temel veri kaynağındaki değişiklikleri izlemek için bir gözlemci uygulayabilir. Örneğin CursorLoader, veri değiştiğinde yeniden yüklemeyi tetiklemek için otomatik olarak bir ContentObserver kaydeder.

Loader API özeti

Bir uygulamada yükleyicileri kullanırken yararlanılabilecek birden fazla sınıf ve arayüz vardır. Bunlar aşağıdaki tabloda özetlenmiştir:

Ders/Arayüz Açıklama
LoaderManager Bir veya daha fazla Loader örneğini yönetmek için FragmentActivity ya da Fragment ile ilişkilendirilmiş soyut bir sınıf. Etkinlik veya parça başına yalnızca bir LoaderManager vardır ancak LoaderManager birden fazla yükleyiciyi yönetebilir.

Bir LoaderManager almak için etkinlikten veya parçadan getSupportLoaderManager() çağrısı yapın.

Yükleyiciden veri yüklemeye başlamak için initLoader() veya restartLoader() yöntemini çağırın. Sistem, aynı tam sayı kimliğine sahip bir yükleyicinin zaten mevcut olup olmadığını otomatik olarak belirler ve yeni bir yükleyici oluşturur veya mevcut bir yükleyiciyi yeniden kullanır.

LoaderManager.LoaderCallbacks Bu arayüz, yükleyici etkinlikleri gerçekleştiğinde çağrılan geri çağırma yöntemlerini içerir. Arayüzde üç geri çağırma yöntemi tanımlanır:
  • onCreateLoader(int, Bundle): Sistemin yeni bir yükleyici oluşturulması gerektiğinde çağrılır. Kodunuzda bir Loader nesnesi oluşturun ve bunu sisteme döndürün.
  • onLoadFinished(Loader<D>, D): Bir yükleyici veri yüklemeyi bitirdiğinde çağrılır. Verileri genellikle kodunuzda kullanıcıya gösterirsiniz.
  • onLoaderReset(Loader<D>): Önceden oluşturulmuş bir yükleyici sıfırlanırken, destroyLoader(int) yöntemini çağırdığınızda veya etkinlik ya da parça kaldırılırken ve içerdiği veriler kullanılamaz hale geldiğinde çağrılır. Kodunuzda, yükleyici verilerine yapılan tüm referansları kaldırın.
Etkinliğiniz veya parçanız genellikle bu arayüzü uygular ve initLoader() veya restartLoader() çağırdığınızda kaydedilir.
Loader Veri yükleme işlemini yükleyiciler gerçekleştirir. Bu sınıf soyuttır ve tüm yükleyiciler için temel sınıf işlevi görür. Doğrudan Loader alt sınıfını kullanabilir veya uygulamayı basitleştirmek için aşağıdaki yerleşik alt sınıflardan birini kullanabilirsiniz:

Aşağıdaki bölümlerde bu sınıf ve arayüzlerin bir uygulamada nasıl kullanılacağı gösterilmektedir.

Uygulamada yükleyicileri kullanma

Bu bölümde, yükleyicilerin Android uygulamalarında nasıl kullanılacağı açıklanmaktadır. Yükleyicileri kullanan bir uygulama genellikle aşağıdakileri içerir:

Yükleyici başlatın

LoaderManager, FragmentActivity veya Fragment içinde bir veya daha fazla Loader örneğini yönetir. Etkinlik veya parça başına yalnızca bir LoaderManager vardır.

Genellikle etkinliğin onCreate() veya parçanın onCreate() yönteminde bir Loader başlatırsınız. Bu işlem şu şekilde yapılır:

Kotlin

supportLoaderManager.initLoader(0, null, this)

Java

// Prepare the loader.  Either re-connect with an existing one,
// or start a new one.
getSupportLoaderManager().initLoader(0, null, this);

initLoader() yöntemi aşağıdaki parametreleri alır:

  • Yükleyiciyi tanımlayan benzersiz kimlik. Bu örnekte kimlik 0'tır.
  • Oluşturma sırasında yükleyiciye sağlanacak isteğe bağlı bağımsız değişkenlerdir (bu örnekte null).
  • LoaderManager öğesinin, yükleyici etkinliklerini raporlamak için çağırdığı LoaderManager.LoaderCallbacks uygulaması. Bu örnekte, yerel sınıf LoaderManager.LoaderCallbacks arayüzünü uyguladığından kendisine bir referans (this) iletir.

initLoader() çağrısı, bir yükleyicinin başlatılmasını ve etkin olmasını sağlar. Bunun iki olası sonucu vardır:

  • Kimlik tarafından belirtilen yükleyici zaten varsa son oluşturulan yükleyici yeniden kullanılır.
  • Kimlikle belirtilen yükleyici yoksa initLoader(), LoaderManager.LoaderCallbacks yöntemini onCreateLoader() tetikler. Burası, yeni bir yükleyici örneklendirmek ve döndürmek için kodu uygulayacağınız yerdir. Daha fazla bilgi için onCreateLoader ile ilgili bölüme bakın.

Her iki durumda da, belirtilen LoaderManager.LoaderCallbacks uygulaması yükleyiciyle ilişkilendirilir ve yükleyici durumu değiştiğinde çağrılır. Bu çağrı sırasında arayan kişi başlatılmış durumundaysa ve istenen yükleyici zaten varsa ve verilerini oluşturduysa sistem initLoader() sırasında hemen onLoadFinished() yöntemini çağırır. Böyle bir durum karşısında hazırlıklı olmalısınız. Bu geri çağırma hakkında daha ayrıntılı bilgi için onLoadFinished ile ilgili bölüme bakın.

initLoader() yöntemi, oluşturulan Loader değerini döndürür, ancak bunun için bir referans yakalamanız gerekmez. LoaderManager, yükleyicinin ömrünü otomatik olarak yönetir. LoaderManager, gerektiğinde yüklenmeye başlar, durur ve yükleyici ile ilişkilendirilmiş içeriğinin durumunu korur.

Bu nedenle, yükleyicilerle nadiren doğrudan etkileşime giriyorsunuz. Belirli etkinlikler gerçekleştiğinde yükleme sürecine müdahale etmek için genellikle LoaderManager.LoaderCallbacks yöntemlerini kullanırsınız. Bu konuyla ilgili daha fazla açıklama için LoaderManager geri çağırmalarını kullanma bölümüne bakın.

Yükleyiciyi yeniden başlatma

Önceki bölümde gösterildiği gibi initLoader() kullandığınızda, belirtilen kimliğe sahip mevcut bir yükleyici (varsa) kullanılır. Herhangi bir dosya yoksa bir tane oluşturur. Ancak bazen eski verilerinizi silip baştan başlamak istersiniz.

Eski verilerinizi silmek için restartLoader() uygulamasını kullanın. Örneğin, aşağıdaki SearchView.OnQueryTextListener uygulaması, kullanıcının sorgusu değiştiğinde yükleyiciyi yeniden başlatır. Yükleyicinin yeni bir sorgu yaparken düzeltilmiş arama filtresini kullanabilmesi için yeniden başlatılması gerekir.

Kotlin

fun onQueryTextChanged(newText: String?): Boolean {
    // Called when the action bar search text has changed.  Update
    // the search filter and restart the loader to do a new query
    // with this filter.
    curFilter = if (newText?.isNotEmpty() == true) newText else null
    supportLoaderManager.restartLoader(0, null, this)
    return true
}

Java

public boolean onQueryTextChanged(String newText) {
    // Called when the action bar search text has changed.  Update
    // the search filter, and restart the loader to do a new query
    // with this filter.
    curFilter = !TextUtils.isEmpty(newText) ? newText : null;
    getSupportLoaderManager().restartLoader(0, null, this);
    return true;
}

LoaderManager geri çağırmalarını kullanma

LoaderManager.LoaderCallbacks, istemcinin LoaderManager ile etkileşim kurmasını sağlayan bir geri çağırma arayüzüdür.

Yükleyicilerin, özellikle de CursorLoader ürününün, durdurulduktan sonra verilerini saklaması beklenir. Böylece uygulamalar, etkinlik veya parçanın onStop() ve onStart() yöntemlerinde verilerini koruyabilir. Böylece, kullanıcılar uygulamaya döndüğünde verilerin yeniden yüklenmesini beklemek zorunda kalmazlar.

Yeni bir yükleyicinin ne zaman oluşturulacağını bilmek ve uygulamaya bir yükleyicinin verilerini kullanmayı ne zaman durdurması gerektiğini bildirmek için LoaderManager.LoaderCallbacks yöntemlerini kullanırsınız.

LoaderManager.LoaderCallbacks şu yöntemleri içerir:

  • onLoadFinished(): Önceden oluşturulmuş bir yükleyici yükleme işlemini tamamladığında çağrılır.
  • onLoaderReset(): Bu, daha önce oluşturulmuş bir yükleyici sıfırlanıp verileri kullanılamaz hale geldiğinde çağrılır.

Bu yöntemler aşağıdaki bölümlerde daha ayrıntılı olarak açıklanmaktadır.

onCreateLoader

Bir yükleyiciye (ör. initLoader() üzerinden) erişmeye çalıştığınızda, kimlik tarafından belirtilen yükleyicinin var olup olmadığını kontrol eder. Aksi takdirde onCreateLoader() LoaderManager.LoaderCallbacks yöntemini tetikler. Burada yeni bir yükleyici oluşturursunuz. Bu genellikle bir CursorLoader'dir, ancak kendi Loader alt sınıfınızı da uygulayabilirsiniz.

Aşağıdaki örnekte onCreateLoader() geri çağırma yöntemi, oluşturucu yöntemini kullanarak bir CursorLoader oluşturur. Bu yöntem, ContentProvider öğesine bir sorgu gerçekleştirmek için gereken bilgilerin tamamını gerektirir. Özel olarak aşağıdakiler gereklidir:

  • uri: Alınacak içeriğin URI'si.
  • projeksiyon: Döndürülecek sütunların listesi. null geçirildiğinde tüm sütunlar döndürülür ve bu verimsizdir.
  • selection: Hangi satırların döndürüleceğini bildiren, SQL WHERE deyimi olarak biçimlendirilmiş bir filtre (WHERE öğesinin kendisi hariç). null değerinin iletilmesi, belirtilen URI için tüm satırları döndürür.
  • selectionArgs: Seçime ?s eklerseniz bunlar, seçimde göründükleri sırayla selectionArgs'teki değerlerle değiştirilir. Değerler dize olarak bağlanmıştır.
  • sortOrder: SQL ORDER BY yan tümcesi olarak biçimlendirilmiş satırların nasıl sıralanacağı (ORDER BY'nin kendisi hariç). null iletildiğinde, varsayılan sıralama ölçütü kullanılır. Bu sırasız olabilir.

Kotlin

// If non-null, this is the current filter the user has provided.
private var curFilter: String? = null
...
override fun onCreateLoader(id: Int, args: Bundle?): Loader<Cursor> {
    // This is called when a new Loader needs to be created.  This
    // sample only has one Loader, so we don't care about the ID.
    // First, pick the base URI to use depending on whether we are
    // currently filtering.
    val baseUri: Uri = if (curFilter != null) {
        Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_URI, Uri.encode(curFilter))
    } else {
        ContactsContract.Contacts.CONTENT_URI
    }

    // Now create and return a CursorLoader that will take care of
    // creating a Cursor for the data being displayed.
    val select: String = "((${Contacts.DISPLAY_NAME} NOTNULL) AND (" +
            "${Contacts.HAS_PHONE_NUMBER}=1) AND (" +
            "${Contacts.DISPLAY_NAME} != ''))"
    return (activity as? Context)?.let { context ->
        CursorLoader(
                context,
                baseUri,
                CONTACTS_SUMMARY_PROJECTION,
                select,
                null,
                "${Contacts.DISPLAY_NAME} COLLATE LOCALIZED ASC"
        )
    } ?: throw Exception("Activity cannot be null")
}

Java

// If non-null, this is the current filter the user has provided.
String curFilter;
...
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
    // This is called when a new Loader needs to be created.  This
    // sample only has one Loader, so we don't care about the ID.
    // First, pick the base URI to use depending on whether we are
    // currently filtering.
    Uri baseUri;
    if (curFilter != null) {
        baseUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI,
                  Uri.encode(curFilter));
    } else {
        baseUri = Contacts.CONTENT_URI;
    }

    // Now create and return a CursorLoader that will take care of
    // creating a Cursor for the data being displayed.
    String select = "((" + Contacts.DISPLAY_NAME + " NOTNULL) AND ("
            + Contacts.HAS_PHONE_NUMBER + "=1) AND ("
            + Contacts.DISPLAY_NAME + " != '' ))";
    return new CursorLoader(getActivity(), baseUri,
            CONTACTS_SUMMARY_PROJECTION, select, null,
            Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC");
}

onLoadFinished

Bu yöntem, daha önce oluşturulan bir yükleyicinin yüklemesini bitirdiğinde çağrılır. Bu yöntemin, bu yükleyici için sağlanan son verilerin yayınlanmasından önce çağrılması garanti edilir. Bu noktada, eski veriler kullanıma sunulacağından, bunların tüm kullanımını kaldırın. Ancak verileri kendiniz serbest bırakmayın. Veriler yükleyiciye aittir ve ilgilenir.

Yükleyici, uygulamanın artık kullanmadığını öğrendikten sonra verileri serbest bırakır. Örneğin, veriler bir CursorLoader öğesinden gelen imleçse bunun için close() çağrısı yapmayın. İmleç bir CursorAdapter içine yerleştiriliyorsa aşağıdaki örnekte gösterildiği gibi eski Cursor öğesinin kapanmaması için swapCursor() yöntemini kullanın:

Kotlin

private lateinit var adapter: SimpleCursorAdapter
...
override fun onLoadFinished(loader: Loader<Cursor>, data: Cursor?) {
    // Swap the new cursor in. (The framework will take care of closing the
    // old cursor once we return.)
    adapter.swapCursor(data)
}

Java

// This is the Adapter being used to display the list's data.
SimpleCursorAdapter adapter;
...
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
    // Swap the new cursor in. (The framework will take care of closing the
    // old cursor once we return.)
    adapter.swapCursor(data);
}

onLoaderSıfırla

Bu yöntem, daha önce oluşturulan bir yükleyici sıfırlanırken ve dolayısıyla verileri kullanılamaz hale geldiğinde çağrılır. Bu geri çağırma, verilerin ne zaman yayınlanmak üzere olduğunu öğrenmenizi ve böylece referansınızı kaldırabilmenizi sağlar.

Bu uygulama null değerine sahip swapCursor() işlevini çağırır:

Kotlin

private lateinit var adapter: SimpleCursorAdapter
...
override fun onLoaderReset(loader: Loader<Cursor>) {
    // This is called when the last Cursor provided to onLoadFinished()
    // above is about to be closed.  We need to make sure we are no
    // longer using it.
    adapter.swapCursor(null)
}

Java

// This is the Adapter being used to display the list's data.
SimpleCursorAdapter adapter;
...
public void onLoaderReset(Loader<Cursor> loader) {
    // This is called when the last Cursor provided to onLoadFinished()
    // above is about to be closed.  We need to make sure we are no
    // longer using it.
    adapter.swapCursor(null);
}

Örnek

Örnek olarak, kişiler içerik sağlayıcısına karşı yapılan sorgunun sonuçlarını içeren bir ListView görüntüleyen Fragment öğesinin tam uygulaması şu şekildedir. Sağlayıcıdaki sorguyu yönetmek için bir CursorLoader kullanır.

Bu örnek, kullanıcının kişilerine erişmek için kullanılan bir uygulamadan geldiğinden manifest dosyası READ_CONTACTS iznini içermelidir.

Kotlin

private val CONTACTS_SUMMARY_PROJECTION: Array<String> = arrayOf(
        Contacts._ID,
        Contacts.DISPLAY_NAME,
        Contacts.CONTACT_STATUS,
        Contacts.CONTACT_PRESENCE,
        Contacts.PHOTO_ID,
        Contacts.LOOKUP_KEY
)


class CursorLoaderListFragment :
        ListFragment(),
        SearchView.OnQueryTextListener,
        LoaderManager.LoaderCallbacks<Cursor> {

    // This is the Adapter being used to display the list's data.
    private lateinit var mAdapter: SimpleCursorAdapter

    // If non-null, this is the current filter the user has provided.
    private var curFilter: String? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // Prepare the loader.  Either re-connect with an existing one,
        // or start a new one.
        loaderManager.initLoader(0, null, this)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        // Give some text to display if there is no data.  In a real
        // application, this would come from a resource.
        setEmptyText("No phone numbers")

        // We have a menu item to show in action bar.
        setHasOptionsMenu(true)

        // Create an empty adapter we will use to display the loaded data.
        mAdapter = SimpleCursorAdapter(activity,
                android.R.layout.simple_list_item_2,
                null,
                arrayOf(Contacts.DISPLAY_NAME, Contacts.CONTACT_STATUS),
                intArrayOf(android.R.id.text1, android.R.id.text2),
                0
        )
        listAdapter = mAdapter
    }

    override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
        // Place an action bar item for searching.
        menu.add("Search").apply {
            setIcon(android.R.drawable.ic_menu_search)
            setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM)
            actionView = SearchView(activity).apply {
                setOnQueryTextListener(this@CursorLoaderListFragment)
            }
        }
    }

    override fun onQueryTextChange(newText: String?): Boolean {
        // Called when the action bar search text has changed.  Update
        // the search filter, and restart the loader to do a new query
        // with this filter.
        curFilter = if (newText?.isNotEmpty() == true) newText else null
        loaderManager.restartLoader(0, null, this)
        return true
    }

    override fun onQueryTextSubmit(query: String): Boolean {
        // Don't care about this.
        return true
    }

    override fun onListItemClick(l: ListView, v: View, position: Int, id: Long) {
        // Insert desired behavior here.
        Log.i("FragmentComplexList", "Item clicked: $id")
    }

    override fun onCreateLoader(id: Int, args: Bundle?): Loader<Cursor> {
        // This is called when a new Loader needs to be created.  This
        // sample only has one Loader, so we don't care about the ID.
        // First, pick the base URI to use depending on whether we are
        // currently filtering.
        val baseUri: Uri = if (curFilter != null) {
            Uri.withAppendedPath(Contacts.CONTENT_URI, Uri.encode(curFilter))
        } else {
            Contacts.CONTENT_URI
        }

        // Now create and return a CursorLoader that will take care of
        // creating a Cursor for the data being displayed.
        val select: String = "((${Contacts.DISPLAY_NAME} NOTNULL) AND (" +
                "${Contacts.HAS_PHONE_NUMBER}=1) AND (" +
                "${Contacts.DISPLAY_NAME} != ''))"
        return (activity as? Context)?.let { context ->
            CursorLoader(
                    context,
                    baseUri,
                    CONTACTS_SUMMARY_PROJECTION,
                    select,
                    null,
                    "${Contacts.DISPLAY_NAME} COLLATE LOCALIZED ASC"
            )
        } ?: throw Exception("Activity cannot be null")
    }

    override fun onLoadFinished(loader: Loader<Cursor>, data: Cursor) {
        // Swap the new cursor in.  (The framework will take care of closing the
        // old cursor once we return.)
        mAdapter.swapCursor(data)
    }

    override fun onLoaderReset(loader: Loader<Cursor>) {
        // This is called when the last Cursor provided to onLoadFinished()
        // above is about to be closed.  We need to make sure we are no
        // longer using it.
        mAdapter.swapCursor(null)
    }
}

Java

public static class CursorLoaderListFragment extends ListFragment
        implements OnQueryTextListener, LoaderManager.LoaderCallbacks<Cursor> {

    // This is the Adapter being used to display the list's data.
    SimpleCursorAdapter mAdapter;

    // If non-null, this is the current filter the user has provided.
    String curFilter;

    @Override public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Prepare the loader.  Either re-connect with an existing one,
        // or start a new one.
        getLoaderManager().initLoader(0, null, this);
    }

    @Override public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        // Give some text to display if there is no data.  In a real
        // application, this would come from a resource.
        setEmptyText("No phone numbers");

        // We have a menu item to show in action bar.
        setHasOptionsMenu(true);

        // Create an empty adapter we will use to display the loaded data.
        mAdapter = new SimpleCursorAdapter(getActivity(),
                android.R.layout.simple_list_item_2, null,
                new String[] { Contacts.DISPLAY_NAME, Contacts.CONTACT_STATUS },
                new int[] { android.R.id.text1, android.R.id.text2 }, 0);
        setListAdapter(mAdapter);
    }

    @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        // Place an action bar item for searching.
        MenuItem item = menu.add("Search");
        item.setIcon(android.R.drawable.ic_menu_search);
        item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
        SearchView sv = new SearchView(getActivity());
        sv.setOnQueryTextListener(this);
        item.setActionView(sv);
    }

    public boolean onQueryTextChange(String newText) {
        // Called when the action bar search text has changed.  Update
        // the search filter, and restart the loader to do a new query
        // with this filter.
        curFilter = !TextUtils.isEmpty(newText) ? newText : null;
        getLoaderManager().restartLoader(0, null, this);
        return true;
    }

    @Override public boolean onQueryTextSubmit(String query) {
        // Don't care about this.
        return true;
    }

    @Override public void onListItemClick(ListView l, View v, int position, long id) {
        // Insert desired behavior here.
        Log.i("FragmentComplexList", "Item clicked: " + id);
    }

    // These are the Contacts rows that we will retrieve.
    static final String[] CONTACTS_SUMMARY_PROJECTION = new String[] {
        Contacts._ID,
        Contacts.DISPLAY_NAME,
        Contacts.CONTACT_STATUS,
        Contacts.CONTACT_PRESENCE,
        Contacts.PHOTO_ID,
        Contacts.LOOKUP_KEY,
    };
    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
        // This is called when a new Loader needs to be created.  This
        // sample only has one Loader, so we don't care about the ID.
        // First, pick the base URI to use depending on whether we are
        // currently filtering.
        Uri baseUri;
        if (curFilter != null) {
            baseUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI,
                    Uri.encode(curFilter));
        } else {
            baseUri = Contacts.CONTENT_URI;
        }

        // Now create and return a CursorLoader that will take care of
        // creating a Cursor for the data being displayed.
        String select = "((" + Contacts.DISPLAY_NAME + " NOTNULL) AND ("
                + Contacts.HAS_PHONE_NUMBER + "=1) AND ("
                + Contacts.DISPLAY_NAME + " != '' ))";
        return new CursorLoader(getActivity(), baseUri,
                CONTACTS_SUMMARY_PROJECTION, select, null,
                Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC");
    }

    public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
        // Swap the new cursor in.  (The framework will take care of closing the
        // old cursor once we return.)
        mAdapter.swapCursor(data);
    }

    public void onLoaderReset(Loader<Cursor> loader) {
        // This is called when the last Cursor provided to onLoadFinished()
        // above is about to be closed.  We need to make sure we are no
        // longer using it.
        mAdapter.swapCursor(null);
    }
}

Diğer örnekler

Aşağıdaki örneklerde yükleyicilerin nasıl kullanılacağı gösterilmektedir:

  • LoaderCursor: Önceki snippet'in tam sürümü.
  • Kişiler listesi alma: Kişi sağlayıcısından veri almak için CursorLoader kullanan bir adım adım açıklamalı kılavuz.
  • LoaderThrottle: Bir içerik sağlayıcının verileri değiştiğinde gerçekleştirdiği sorgu sayısını azaltmak için kısıtlamanın nasıl kullanılacağına dair bir örnek.