מטענים הוצאו משימוש החל מ-Android 9 (רמת API 28). האפשרות המומלצת עבור
בנושא טעינת נתונים במהלך טיפול במחזורי החיים של Activity
ו-Fragment
,
שילוב של ViewModel
אובייקטים
ו-LiveData
.
הצגת המודלים לשרוד שינויים בתצורה, כמו מטענים, אבל עם
פחות קוד סטנדרטי. LiveData
מספק דרך לטעינת נתונים בהתאם למחזור החיים שניתן לעשות בהם שימוש חוזר
מודלים מרובים של תצוגה. אפשר גם לשלב את LiveData
באמצעות
MediatorLiveData
.
כל השאילתות שניתנות למדידה, כמו שאילתה
מסד הנתונים של Room – אפשר להשתמש בו כדי להבחין בשינויים
לנתונים.
ViewModel
ו-LiveData
זמינים גם במצבים שבהם אין לך גישה
אל LoaderManager
, למשל
Service
. שימוש בשני הסוגים
tandem מספקת דרך קלה לגשת לנתונים שהאפליקציה שלך צריכה ללא צורך בטיפול בממשק המשתמש
במחזור החיים. מידע נוסף על LiveData
זמין ב
סקירה כללית של LiveData
. מידע נוסף על
ViewModel
, אפשר לעיין בסקירה הכללית של ViewModel
.
ה-Loader API מאפשר לטעון נתונים
ספק תוכן
או מקור נתונים אחר להצגה בFragmentActivity
או Fragment
.
ללא מטענים, יכול להיות שתיתקלו בבעיות הבאות:
- אם אתם מאחזרים את הנתונים ישירות בפעילות או במקטע, המשתמשים שלכם סובלים מחוסר תגובה בגלל שהביצועים עשויים להיות איטיים מהשרשור של ממשק המשתמש.
- אם מאחזרים את הנתונים משרשור אחר, אולי באמצעות
AsyncTask
, אז אתם אחראים לנהל גם את השרשורים האלה והשרשור בממשק המשתמש, שעובר דרך אירועים שונים של פעילות או מחזור חיים של מקטעים, כמוonDestroy()
ושינויים בהגדרות האישיות.
מטענים פותרים את הבעיות האלה וכוללים יתרונות נוספים:
- מטענים פועלים בשרשורים נפרדים כדי למנוע ממשק משתמש איטי או לא מגיב.
- טעינות הנתונים מפשטות את ניהול השרשורים באמצעות שיטות קריאה חוזרת (callback) כשאירועים יתרחשו.
- המטענים נשארים ושומרים את התוצאות במטמון בכל שינויי ההגדרות כדי למנוע של שאילתות כפולות.
- מטענים יכולים להטמיע צופה כדי לנטר את השינויים
מקור הנתונים. לדוגמה,
CursorLoader
באופן אוטומטי רושםContentObserver
כדי להפעיל טעינה מחדש כשהנתונים משתנים.
סיכום של Loader API
יש מספר מחלקות וממשקים שעשויים להיות מעורבים בשימוש טעינה באפליקציה. הסיכום שלהם מוצג בטבלה הבאה:
כיתה/ממשק | תיאור |
---|---|
LoaderManager |
כיתה מופשטת שמשויכת לFragmentActivity או
Fragment לניהול חשבון אחד או יותר
Loader מופעים. יש רק אחד
LoaderManager לכל פעילות או מקטע, אבל
LoaderManager יכול לנהל מטענים מרובים.
כדי לקבל כדי להתחיל לטעון נתונים מטוען, צריך לבצע קריאה לאחד
|
LoaderManager.LoaderCallbacks |
הממשק הזה מכיל שיטות לקריאה חוזרת (callback) שנקראות כאשר
ואירועי Loader מתרחשים. בממשק מוגדרות שלוש שיטות לקריאה חוזרת (callback):
initLoader() או
restartLoader() .
|
Loader |
טוענים מבצעים את טעינת הנתונים. הכיתה הזו מופשטת ומוצגת
כסיווג הבסיס לכל המטענים. אפשר לבצע תת-מחלקה ישירות
Loader או להשתמש באחד מהדפדפנים המובְנים הבאים
מחלקות משנה כדי לפשט את ההטמעה:
|
בקטעים הבאים מוסבר איך להשתמש מחלקות וממשקים באפליקציה.
שימוש במטענים באפליקציה
הקטע הזה מתאר איך להשתמש במטענים באפליקציה ל-Android. אפליקציה שמשתמשת במטענים בדרך כלל כוללת את הפרטים הבאים:
FragmentActivity
אוFragment
.- מופע של
LoaderManager
. CursorLoader
לטעינת נתונים שמגובים על ידיContentProvider
. לחלופין, אתם יכולים להטמיע מחלקה משנית משלכם שלLoader
אוAsyncTaskLoader
עד לטעון נתונים ממקור אחר.- הטמעה של
LoaderManager.LoaderCallbacks
. כאן יוצרים מטענים חדשים ומנהלים את ההפניות לקבצים קיימים בטעינה. - דרך להציג את נתוני הטוען, כמו
SimpleCursorAdapter
. - מקור נתונים, כמו
ContentProvider
, כשמשתמשיםCursorLoader
.
הפעלת כלי טעינה
השדה LoaderManager
מנהל מופע אחד או יותר של Loader
בתוך FragmentActivity
או
Fragment
יש רק LoaderManager
אחד לכל פעילות או מקטע.
בדרך כלל
לאתחל Loader
בתוך ה-method של onCreate()
של הפעילות או של המקטע
אמצעי תשלום אחד (onCreate()
). שלך
עושים זאת כך:
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);
ל-method initLoader()
נדרש
את הפרמטרים הבאים:
- מזהה ייחודי שמזהה את הטוענים. בדוגמה הזו, המזהה הוא
0
. - ארגומנטים אופציונליים שצריך לספק למטען ב-
עבודות בדרך (
null
בדוגמה הזו). - הטמעת
LoaderManager.LoaderCallbacks
, הקריאות שלLoaderManager
לדיווח על אירועי טעינה. כאן לדוגמה, המחלקה המקומית מממשת את הממשק שלLoaderManager.LoaderCallbacks
ולכן היא מעבירה הפניה לעצמו,this
.
הקריאה initLoader()
מבטיחה שהטעינה
מאותחל ופעיל. יש לכך שתי תוצאות אפשריות:
- אם הטוען שצוין במזהה כבר קיים, הטוען האחרון שנוצר נעשה שימוש חוזר.
- אם הטוען שצוין במזהה לא קיים,
הפקודה
initLoader()
מפעילה את אמצעי התשלוםLoaderManager.LoaderCallbacks
onCreateLoader()
. כאן מיישמים את הקוד כדי ליצור מופע ולהחזיר Loader חדש. לדיון נוסף, עיינו בקטע עלonCreateLoader
.
בכל מקרה, הערך הנתון של LoaderManager.LoaderCallbacks
משויך לטוען והוא מופעל כאשר
שינויים במצב ה-Loader. אם, בנקודת השיחה הזו, המתקשר נמצא
והטוען המבוקש כבר קיים ויצר
ואז המערכת קוראת ל-onLoadFinished()
מיד, במהלך initLoader()
. אתם צריכים להיות מוכנים לכך. לדיון נוסף על הקריאה החוזרת הזו, אפשר לעיין בקטע בנושא
onLoadFinished
ה-method initLoader()
מחזירה את הערך Loader
שנוצר,
אבל אין צורך לתעד אליו הפניה. LoaderManager
מנהלת
באופן אוטומטי. LoaderManager
הטעינה מתחילה ומפסיקה במקרה הצורך ושומרת על מצב הטעינה
ואת התוכן המשויך אליו.
כלומר, לעיתים נדירות אין לך אינטראקציה עם מטענים
ישירות.
בדרך כלל משתמשים בשיטות LoaderManager.LoaderCallbacks
כדי להתערב בטעינה
כאשר מתרחשים אירועים מסוימים. לדיון נוסף בנושא הזה, ראו שימוש בקריאות חוזרות (callbacks) של LoaderManager.
הפעלה מחדש של מכשיר טעינה
כשמשתמשים ב-initLoader()
, כמו
שמוצג בקטע הקודם, הוא משתמש בטוען קיים עם המזהה שצוין, אם קיים.
אם אין קובץ כזה, הוא יוצר אתר כזה. אבל לפעמים רוצים למחוק נתונים ישנים
ולהתחיל מחדש.
כדי למחוק נתונים ישנים, צריך להשתמש ב-restartLoader()
. לדוגמה,
הטמעה של SearchView.OnQueryTextListener
הפעלות מחדש
של הטעינות, כשהשאילתה של המשתמש משתנה. צריך להפעיל מחדש את המטען
שהוא יוכל להשתמש במסנן החיפוש המתוקן כדי ליצור שאילתה חדשה.
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; }
שימוש בקריאות חוזרות (callbacks) של LoaderManager
LoaderManager.LoaderCallbacks
הוא ממשק קריאה חוזרת
שמאפשרת ללקוח ליצור אינטראקציה עם LoaderManager
.
אדמינים, במיוחד CursorLoader
, צפויים
ישמרו את הנתונים שלהם אחרי שיופסקו. כך האפליקציות יכולות לשמור
נתונים בכל ה-methods onStop()
ו-onStart()
של הפעילות או המקטע, כך
כשמשתמשים חוזרים לאפליקציה, הם לא צריכים להמתין לנתונים
לטעון מחדש.
משתמשים בשיטות LoaderManager.LoaderCallbacks
כדי לדעת מתי ליצור טוען חדש ולציין לאפליקציה מתי
כדי להפסיק להשתמש בנתוני Loader.
LoaderManager.LoaderCallbacks
כולל אלה
אמצעי תשלום:
onCreateLoader()
: יוצרת ומחזירה ערךLoader
חדש למזהה הנתון.
-
onLoadFinished()
: שנקראה כאשר טוען שנוצר בעבר סיים את הטעינה.
onLoaderReset()
: שנקראה כשטוען שנוצר בעבר מתאפס, וכך הופך הנתונים אינם זמינים.
השיטות האלה מתוארות בפירוט בקטעים הבאים.
onCreateLoader
כשמנסים לגשת לרכיב טעינה, למשל דרך initLoader()
, המערכת בודקת אם
רכיב הטעינה שצוין על ידי המזהה קיים. אם היא לא מתחילה כך, היא מפעילה את השיטה LoaderManager.LoaderCallbacks
onCreateLoader()
. הזה
הוא המקום שבו יוצרים טוען חדש. בדרך כלל זהו מחלקה של CursorLoader
, אבל אתם יכולים להטמיע מחלקה משנית משלכם ב-Loader
.
בדוגמה הבאה, הפרמטר onCreateLoader()
שיטת הקריאה החוזרת יוצרת CursorLoader
באמצעות שיטת ה-constructor שלה,
מחייב את כל המידע הנדרש לביצוע שאילתה ב-ContentProvider
. ספציפית, הוא זקוק לדברים הבאים:
- uri: ה-URI של התוכן שצריך לאחזר.
- projection: רשימה של העמודות שצריך להחזיר. מסירות
הפונקציה
null
מחזירה את כל העמודות, והיא לא יעילה. - selection (בחירה): מסנן שקובע אילו שורות להחזיר
בפורמט SQL WHERE (לא כולל WHERE עצמו). מסירות
הפונקציה
null
מחזירה את כל השורות ל-URI הנתון. - selectionArgs: אם תכללו את הסימנים ?s בבחירה, הם מוחלפים בערכים מ-selectionArgs לפי הסדר שבו הם מופיעים את המבחר. הערכים תחומים כמחרוזות.
- sortOrder: איך לסדר את השורות בפורמט SQL
סעיף ORDER BY (לא כולל ORDER BY עצמו). עובר
null
משתמשת בסדר המיון שמוגדר כברירת מחדל, והוא עשוי להיות לא מסודר.
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"); }
onLoadסיימתי
מתבצעת קריאה לשיטה הזו כאשר טעינה שנוצרה בעבר מסיימת את הטעינה. מובטחת קריאה לשיטה הזו לפני הפצת הנתונים האחרונים שסופק לטעינת הנתונים הזו. בשלב הזה, הסירו את כל השימוש ב- את הנתונים הישנים, כי הם יושקו. עם זאת, אל תפרסמו את הנתונים. בעצמך - הטוען הוא הבעלים שלו ומטפל בזה.
הטוען משחרר את הנתונים לאחר שהוא יודע שהאפליקציה כבר לא
באמצעותו. לדוגמה, אם הנתונים הם סמן מ-CursorLoader
,
אל תתקשרו אל close()
בעצמכם. אם הסמן
משויך ל-CursorAdapter
, צריך להשתמש בשיטה swapCursor()
כדי
הישן Cursor
לא סגור, כמו שאפשר לראות בדוגמה הבאה:
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); }
onLoaderreset
לשיטה הזו קוראים כשמתבצע איפוס של טוען שנוצר בעבר, והנתונים שבו לא זמינים. הקריאה החוזרת מאפשרת לכם לגלות מתי הנתונים ישוחרר כדי שתוכלו להסיר את ההפניה אליו.
ההטמעה הזאת קוראת
swapCursor()
עם הערך 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); }
דוגמה
לדוגמה, הנה ההטמעה המלאה של Fragment
שמציג ListView
שמכיל
תוצאות השאילתה מול ספק התוכן של אנשי הקשר. נעשה שימוש ב-CursorLoader
כדי לנהל את השאילתה אצל הספק.
מכיוון שהדוגמה הזו מגיעה מאפליקציה לגישה לאנשי הקשר של משתמש,
המניפסט חייב לכלול את ההרשאה
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); } }
דוגמאות נוספות
הדוגמאות הבאות ממחישות איך להשתמש במטענים:
- LoaderCursor: גרסה מלאה של קטע הקוד הקודם.
- אחזור רשימה של אנשי קשר:
הדרכה מפורטת שמשתמשת ב-
CursorLoader
כדי לאחזר מספק אנשי הקשר. - LoaderThrottle: דוגמה לאופן שבו ניתן להשתמש בויסות נתונים כדי לצמצם את המספר של שאילתות שספק תוכן מבצע כאשר הנתונים שלו משתנים.