Mit Android 9 (API-Level 28) wurden Ladeprogramme eingestellt. Die empfohlene Option für
das Laden von Daten beim Verarbeiten der Lebenszyklen Activity
und Fragment
ist die Verwendung eines
Kombination aus ViewModel
-Objekten
und LiveData
.
Ansichtsmodelle überdauern Konfigurationsänderungen wie Ladeprogrammen, aber mit
weniger Boilerplate-Code. LiveData
bietet eine Lebenszyklus-orientierte Methode zum Laden von Daten, die Sie wiederverwenden können in
mehrere Ansichtsmodelle nutzen. Sie können auch LiveData
kombinieren mit
MediatorLiveData
Alle beobachtbaren Abfragen, z. B. von einem
Raumdatenbank: Kann zur Beobachtung von Änderungen verwendet werden
zu den Daten hinzufügen.
ViewModel
und LiveData
sind auch verfügbar, wenn du keinen Zugriff hast
an den LoaderManager
, z. B. in einem
Service
Wenn Sie die beiden in
tandem ermöglicht den einfachen Zugriff auf die Daten, die Ihre App benötigt, ohne sich mit der Benutzeroberfläche befassen zu müssen
Lebenszyklus. Weitere Informationen zu LiveData
findest du in der
Übersicht zu LiveData
. Weitere Informationen über
ViewModel
finden Sie in der Übersicht zu ViewModel
.
Mit der Loader API können Sie Daten aus einer
Contentanbieter
oder eine andere Datenquelle zur Anzeige in einem FragmentActivity
oder Fragment
.
Ohne Ladeprogramm können unter anderem folgende Probleme auftreten:
- Wenn Sie die Daten direkt in der Aktivität oder im Fragment abrufen, reagieren nicht schnell, weil sie potenziell langsam sind. Abfragen aus dem UI-Thread.
- Wenn Sie die Daten aus einem anderen Thread abrufen, z. B. mit
AsyncTask
, sind Sie für die Verwaltung beider Threads zuständig, und den UI-Thread durch verschiedene Aktivitäten oder Lebenszyklusereignisse von Fragmenten, wieonDestroy()
und Konfigurationsänderungen.
Loader lösen diese Probleme und bieten weitere Vorteile:
- Loader werden in separaten Threads ausgeführt, um eine langsame oder nicht reagierende Benutzeroberfläche zu verhindern.
- Loader vereinfachen die Thread-Verwaltung, indem sie Callback-Methoden bereitstellen, wenn Ereignisse auftreten.
- Loader bleiben bestehen und speichern Ergebnisse über Konfigurationsänderungen hinweg, um zu verhindern, doppelte Abfragen.
- Loader können einen Beobachter implementieren, um Änderungen in der zugrunde liegenden
Datenquelle verwendet werden. Beispielsweise wird
CursorLoader
automatisch registriert einContentObserver
, um eine Aktualisierung auszulösen. wenn sich Daten ändern.
Loader API – Zusammenfassung
Es gibt mehrere Klassen und Benutzeroberflächen, die bei der Verwendung von Loader in einer App ein. Sie sind in der folgenden Tabelle zusammengefasst:
Klasse/Schnittstelle | Beschreibung |
---|---|
LoaderManager |
Eine abstrakte Klasse, die mit einem FragmentActivity - oder
Fragment für die Verwaltung von mindestens einem
Loader Instanzen. Es gibt nur eine
LoaderManager pro Aktivität oder Fragment, aber ein
LoaderManager kann mehrere Loader verwalten.
Wenn du ein Um mit dem Laden von Daten aus einem Ladeprogramm zu beginnen, rufen Sie entweder
|
LoaderManager.LoaderCallbacks |
Diese Schnittstelle enthält Callback-Methoden, die aufgerufen werden, wenn
loader-Ereignisse auftreten. Die -Schnittstelle definiert drei Callback-Methoden:
<ph type="x-smartling-placeholder">
initLoader() oder
restartLoader()
|
Loader |
Loader laden Daten. Diese Klasse ist abstrakt und dient
als Basisklasse für alle Loader. Sie können direkt abgeleitete Klassen erstellen,
Loader oder eine der folgenden integrierten Funktionen verwenden
abgeleiteten Klassen, um die Implementierung zu vereinfachen:
<ph type="x-smartling-placeholder">
|
In den folgenden Abschnitten erfahren Sie, wie Sie diese Klassen und Schnittstellen in einer Anwendung.
Loader in einer Anwendung verwenden
In diesem Abschnitt wird beschrieben, wie Loader in einer Android-App verwendet werden. Eine -Anwendung, die Loader verwendet, enthält in der Regel Folgendes:
- Ein
FragmentActivity
oderFragment
. - Eine Instanz von
LoaderManager
. - Ein
CursorLoader
zum Laden von Daten, die von einemContentProvider
gestützt werden. Alternativ können Sie Ihre eigene abgeleitete Klasse implementieren vonLoader
oderAsyncTaskLoader
bis Daten aus einer anderen Quelle zu laden. - Eine Implementierung für
LoaderManager.LoaderCallbacks
. Hier erstellen Sie neue Ladeprogramme und verwalten Ihre Verweise auf vorhandene Loader. - Eine Möglichkeit, die Daten des Ladeprogramms anzuzeigen, z. B.
SimpleCursorAdapter
. - Als Datenquelle, z. B.
ContentProvider
, bei Verwendung einerCursorLoader
.
Ladeprogramm starten
Der LoaderManager
verwaltet eine oder mehrere Loader
-Instanzen innerhalb einer FragmentActivity
oder
Fragment
. Es gibt nur eine LoaderManager
pro Aktivität oder Fragment.
Normalerweise
eine Loader
in der onCreate()
-Methode der Aktivität oder im
onCreate()
-Methode. Ich
Gehen Sie dazu wie folgt vor:
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);
Die Methode initLoader()
nimmt
folgende Parameter:
- Eine eindeutige ID, die den Loader identifiziert. In diesem Beispiel lautet die ID
0
. - Optionale Argumente, die an den Loader übergeben werden sollen
Konstruktion (in diesem Beispiel
null
). - Eine
LoaderManager.LoaderCallbacks
-Implementierung, die DieLoaderManager
-Aufrufe zum Melden von Ladeereignissen. In dieser Beispiel: Die lokale Klasse implementiert die SchnittstelleLoaderManager.LoaderCallbacks
und übergibt dann einen Verweis für sich selbst,this
.
Der initLoader()
-Aufruf sorgt dafür, dass ein Loader
initialisiert und aktiv ist. Dies hat zwei mögliche Ergebnisse:
- Wenn der durch die ID angegebene Loader bereits vorhanden ist, wird der zuletzt erstellte Loader wiederverwendet werden.
- Wenn der durch die ID angegebene Loader nicht vorhanden ist,
initLoader()
löst dieLoaderManager.LoaderCallbacks
-MethodeonCreateLoader()
. Hier implementieren Sie den Code zum Instanziieren und Zurückgeben eines neuen Loaders. Weitere Informationen finden Sie im Abschnitt zuonCreateLoader
.
In beiden Fällen wird die angegebene LoaderManager.LoaderCallbacks
-Implementierung ist dem Loader zugeordnet und wird aufgerufen, wenn der
Loader-Status ändert. Wenn sich der Anrufer zum Zeitpunkt des Anrufs im
gestartet. Der angeforderte Loader ist bereits vorhanden und hat seinen
dann ruft das System onLoadFinished()
auf.
sofort, im initLoader()
. Dafür müssen Sie vorbereitet sein. Weitere Informationen zu diesem Callback finden Sie im Abschnitt über .
onLoadFinished
Die Methode initLoader()
gibt den erstellten Loader
zurück.
Sie brauchen aber keinen Verweis
darauf zu erfassen. Der LoaderManager
verwaltet
automatisch die Lebensdauer des Ladeprogramms. Das LoaderManager
startet und beendet den Ladevorgang bei Bedarf und behält den Ladezustand bei
und die zugehörigen Inhalte.
Daher interagieren Sie selten mit Ladeprogrammen.
.
Meistens verwendest du die LoaderManager.LoaderCallbacks
-Methoden, um in den Ladevorgang einzugreifen
wenn bestimmte Ereignisse eintreten. Weitere Informationen zu diesem Thema finden Sie im Abschnitt LoaderManager-Rückrufe verwenden.
Ladeprogramm neu starten
Wenn Sie initLoader()
verwenden,
im vorherigen Abschnitt gezeigt wird, wird ein vorhandener Loader mit der angegebenen ID verwendet, sofern vorhanden.
Ist dies nicht der Fall, wird eine erstellt. Manchmal möchten Sie jedoch Ihre alten Daten
und fangen von vorne an.
Wenn Sie Ihre alten Daten verwerfen möchten, verwenden Sie restartLoader()
. Beispiel:
Implementierung von SearchView.OnQueryTextListener
-Neustarts
wenn sich die Abfrage des Nutzers ändert. Der Loader muss neu gestartet werden,
dass er den überarbeiteten Suchfilter für eine neue Abfrage verwenden kann.
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-Callbacks verwenden
LoaderManager.LoaderCallbacks
ist eine Callback-Oberfläche.
über die ein Client mit der LoaderManager
interagieren kann.
Loader, insbesondere CursorLoader
,
ihre Daten nach dem Beenden behalten. Dadurch können Anwendungen ihre
Daten aus den onStop()
- und onStart()
-Methoden der Aktivität oder des Fragments, sodass
Wenn Nutzende zu einer Anwendung zurückkehren, müssen sie nicht warten, bis die Daten
neu laden.
Mit den LoaderManager.LoaderCallbacks
-Methoden ermitteln Sie, wann ein neuer Loader erstellt werden muss, und teilen der Anwendung mit,
die Daten eines Loaders nicht mehr zu verwenden.
LoaderManager.LoaderCallbacks
enthält diese
Methoden:
onCreateLoader()
: instanziiert eine neueLoader
für die angegebene ID und gibt sie zurück.
-
onLoadFinished()
: wird aufgerufen, wenn ein zuvor erstellter Loader das Laden beendet hat.
onLoaderReset()
: wird aufgerufen, wenn ein zuvor erstellter Loader zurückgesetzt wird. Daten nicht verfügbar.
Diese Methoden werden in den folgenden Abschnitten ausführlicher beschrieben.
onCreateLoader
Wenn Sie versuchen, auf einen Loader zuzugreifen, z. B. über initLoader()
, wird geprüft,
der durch die ID angegebene Ladeprogramm existiert. Ist dies nicht der Fall, wird die LoaderManager.LoaderCallbacks
-Methode onCreateLoader()
ausgelöst. Dieses
erstellen Sie einen neuen Loader. In der Regel ist dies eine CursorLoader
, aber Sie können auch Ihre eigene Loader
-Unterklasse implementieren.
Im folgenden Beispiel wird der onCreateLoader()
-Callback-Methode ein CursorLoader
-Element mithilfe der Konstruktormethode erstellt,
benötigt alle Informationen, die zum Ausführen einer Abfrage an ContentProvider
erforderlich sind. Insbesondere ist Folgendes erforderlich:
- uri: Der URI für den abzurufenden Inhalt.
- Projektion: Eine Liste der zurückzugebenden Spalten. Bestanden
null
gibt alle Spalten zurück, was ineffizient ist. - selection: ein Filter, der angibt, welche Zeilen zurückgegeben werden sollen
als SQL-WHERE-Klausel formatiert (ohne das WHERE selbst). Bestanden
null
gibt alle Zeilen für den angegebenen URI zurück. - selectionArgs: Wenn Sie „?s“ in der Auswahl verwenden, werden sie werden durch die Werte aus selectionArgs in der Reihenfolge ersetzt, in der sie in ausgewählt haben. Die Werte sind als Strings gebunden.
- sortOrder: Reihenfolge der als SQL formatierten Zeilen
ORDER BY-Klausel (ohne ORDER BY selbst). Bestanden:
null
verwendet die Standardsortierreihenfolge, die möglicherweise ungeordnet ist.
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 (OnLoadAbgeschlossen)
Diese Methode wird aufgerufen, wenn ein zuvor erstellter Loader das Laden beendet. Diese Methode wird garantiert vor der Freigabe der letzten Daten aufgerufen. der für diesen Loader bereitgestellt wird. Entfernen Sie an dieser Stelle jegliche Verwendung von da sie veröffentlicht werden. Geben Sie die Daten aber nicht weiter. der Loader gehört und sich darum kümmert.
Das Ladeprogramm gibt die Daten frei, sobald es weiß, dass die Anwendung nicht mehr
verwenden. Wenn die Daten beispielsweise ein Cursor von einem CursorLoader
sind,
Rufen Sie close()
nicht selbst auf. Wenn sich der Cursor
in einer CursorAdapter
platziert haben, verwenden Sie die Methode swapCursor()
, damit der
Die alte Cursor
ist nicht geschlossen, wie im folgenden Beispiel gezeigt:
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); }
onLoaderZurücksetzen
Diese Methode wird aufgerufen, wenn ein zuvor erstellter Loader zurückgesetzt wird. wodurch die Daten nicht mehr verfügbar sind. Mit diesem Callback können Sie herausfinden, wann die Daten veröffentlicht werden, damit Sie Ihren Verweis darauf entfernen können.
Diese Implementierung ruft
swapCursor()
mit einem Wert von null
:
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); }
Beispiel
Als Beispiel ist hier die vollständige Implementierung eines Fragment
-Elements, bei dem ein ListView
-Element angezeigt wird, das
die Ergebnisse einer Abfrage beim Contentanbieter für Kontakte. Die Abfrage beim Anbieter wird mit einem CursorLoader
verwaltet.
Da dieses Beispiel aus einer Anwendung für den Zugriff auf die Kontakte eines Nutzers stammt, ist es
Manifest muss die Berechtigung enthalten,
READ_CONTACTS
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); } }
Weitere Beispiele
Die folgenden Beispiele veranschaulichen die Verwendung von Ladeprogrammen:
- <ph type="x-smartling-placeholder"></ph> LoaderCursor: Eine vollständige Version des vorherigen Snippets.
- Kontaktliste abrufen:
Schritt-für-Schritt-Anleitung, in der ein
CursorLoader
zum Abrufen Daten vom Kontaktanbieter - <ph type="x-smartling-placeholder"></ph> LoaderThrottle: Ein Beispiel für die Verwendung von Drosselung, um die Zahl zu reduzieren. von Abfragen, die ein Contentanbieter durchführt, wenn sich seine Daten ändern.