Android 9 (एपीआई लेवल 28) के बाद से, लोडर बंद कर दिए गए हैं. इसके लिए सुझाया गया विकल्प
Activity
और Fragment
लाइफ़साइकल को हैंडल करते समय, लोड होने वाले डेटा से निपटने के लिए
ViewModel
ऑब्जेक्ट का कॉम्बिनेशन
और LiveData
.
व्यू मॉडल, लोडर की तरह कॉन्फ़िगरेशन में होने वाले बदलावों के बाद भी बचे रहते हैं, लेकिन
कम बॉयलरप्लेट कोड. LiveData
, डेटा लोड होने की लाइफ़साइकल के बारे में जानकारी देने वाला तरीका उपलब्ध कराता है. इसे फिर से इस्तेमाल किया जा सकता है
एक से ज़्यादा व्यू मॉडल का इस्तेमाल कर सकते हैं. LiveData
को जोड़ने के लिए, यह तरीका भी अपनाया जा सकता है:
MediatorLiveData
.
कोई भी मॉनिटर की जा सकने वाली क्वेरी, जैसे कि
रूम डेटाबेस, इसका इस्तेमाल बदलावों के बारे में जानने के लिए किया जा सकता है
ही डेटा में शामिल हो सकते हैं.
ViewModel
और LiveData
उन स्थितियों में भी उपलब्ध होते हैं जहां आपके पास इसका ऐक्सेस नहीं है
को LoaderManager
के लिए, जैसे कि
Service
. दोनों को Google में
टैन्डम, आपके ऐप्लिकेशन के लिए ज़रूरी डेटा को ऐक्सेस करने का आसान तरीका मुहैया कराता है. इसके लिए, यूज़र इंटरफ़ेस (यूआई) की ज़रूरत नहीं होती
लाइफ़साइकल. LiveData
के बारे में ज़्यादा जानने के लिए, यहां जाएं:
LiveData
खास जानकारी. इस बारे में ज़्यादा जानने के लिए
ViewModel
, ViewModel
की खास जानकारी देखें.
Loader API की मदद से, किसी
कॉन्टेंट देने वाला
या FragmentActivity
में दिखाने के लिए कोई दूसरा डेटा सोर्स
या Fragment
.
लोडर न होने पर, आपको नीचे दी गई कुछ समस्याओं का सामना करना पड़ सकता है:
- अगर सीधे गतिविधि या फ़्रैगमेंट में डेटा फ़ेच किया जाता है, तो आपके उपयोगकर्ता संभावित रूप से धीमे काम करने की वजह से, रिस्पॉन्स में समय की कमी की समस्या से जूझ रहे हैं यूज़र इंटरफ़ेस (यूआई) थ्रेड से क्वेरी.
- अगर आपको किसी दूसरे थ्रेड से डेटा फ़ेच करना है, तो शायद
AsyncTask
से, तो दोनों थ्रेड को मैनेज करने की ज़िम्मेदारी आपकी होगी यूज़र इंटरफ़ेस (यूआई) थ्रेड को कई तरह की गतिविधि या फ़्रैगमेंट लाइफ़साइकल इवेंट के ज़रिए दिखाया जाता है. जैसे,onDestroy()
और कॉन्फ़िगरेशन में बदलाव किए गए हैं.
लोडर इन समस्याओं को हल करते हैं और इनके दूसरे फ़ायदे भी हैं:
- धीमे या काम नहीं करने वाले यूज़र इंटरफ़ेस (यूआई) को रोकने के लिए, लोडर अलग-अलग थ्रेड पर चलते हैं.
- इवेंट के दौरान, लोडर कॉलबैक मैथड देकर थ्रेड मैनेजमेंट को आसान बनाते हैं होता है.
- इस विकल्प को रोकने के लिए, लोडर सभी कॉन्फ़िगरेशन में बदलावों को बनाए रखते हैं और नतीजों को कैश मेमोरी में सेव करते हैं डुप्लीकेट क्वेरी.
- लोडर, ऑब्ज़र्वर को लागू करके, मौजूदा डेटा के बदलावों की निगरानी कर सकते हैं
डेटा सोर्स. उदाहरण के लिए,
CursorLoader
अपने-आप फिर से लोड करने के लिएContentObserver
रजिस्टर करता है जब डेटा बदलता है.
Loader API के बारे में खास जानकारी
ऐसी कई क्लास और इंटरफ़ेस हैं जो 'टूल' का इस्तेमाल करते समय लोडर का इस्तेमाल किया जा सकता है. इनकी खास जानकारी यहां दी गई टेबल में दी गई है:
क्लास/इंटरफ़ेस | ब्यौरा |
---|---|
LoaderManager |
FragmentActivity या से जुड़ी ऐब्स्ट्रैक्ट क्लास
एक या उससे ज़्यादा मैनेज करने के लिए Fragment
Loader इंस्टेंस. यहां सिर्फ़ एक
हर गतिविधि या फ़्रैगमेंट के लिए LoaderManager , लेकिन
LoaderManager , एक से ज़्यादा लोडर मैनेज कर सकता है.
लोडर से डेटा लोड करना शुरू करने के लिए, इनमें से किसी एक को कॉल करें
|
LoaderManager.LoaderCallbacks |
इस इंटरफ़ेस में कॉलबैक मेथड होते हैं. इन्हें तब कॉल किया जाता है, जब
लोडर इवेंट होते हैं. इंटरफ़ेस में तीन कॉलबैक तरीके बताए गए हैं:
initLoader() या
restartLoader() .
|
Loader |
लोडर डेटा लोड करने का काम करते हैं. यह क्लास ऐब्सट्रैक्ट है और इसमें अपनी सेवाएं देती है
लोड करने वाले सभी लोगों की बेस क्लास के तौर पर. सीधे तौर पर सब-क्लास बनाई जा सकती है
Loader या पहले से मौजूद इनमें से किसी एक का इस्तेमाल करें
सब-क्लास का इस्तेमाल करके, आसानी से लागू किया जा सकता है:
|
नीचे दिए गए सेक्शन में, क्लास और इंटरफ़ेस पर मौजूद हैं.
ऐप्लिकेशन में लोडर का इस्तेमाल करना
इस सेक्शन में किसी Android ऐप्लिकेशन में लोडर इस्तेमाल करने का तरीका बताया गया है. अगर आप लोडर का इस्तेमाल करने वाले ऐप्लिकेशन में आम तौर पर ये चीज़ें शामिल होती हैं:
FragmentActivity
याFragment
.LoaderManager
का एक इंस्टेंस.ContentProvider
के साथ काम करने वाला डेटा लोड करने के लिएCursorLoader
. इसके अलावा, अपने हिसाब से सब-क्लास भी लागू की जा सकती हैLoader
याAsyncTaskLoader
का किसी अन्य सोर्स से डेटा लोड करें.LoaderManager.LoaderCallbacks
के लिए लागू करने की प्रक्रिया. यहां पर आप नए लोडर बनाते हैं और मौजूदा लोडर.- लोड करने वाले के डेटा को दिखाने का एक तरीका, जैसे कि
SimpleCursorAdapter
. - डेटा सोर्स, जैसे कि
ContentProvider
, जबCursorLoader
.
लोडर चालू करें
LoaderManager
, FragmentActivity
में एक या उससे ज़्यादा Loader
इंस्टेंस मैनेज करता है या
Fragment
. हर गतिविधि या फ़्रैगमेंट के लिए सिर्फ़ एक LoaderManager
होता है.
आम तौर पर
गतिविधि के onCreate()
तरीके या फ़्रैगमेंटLoader
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);
initLoader()
तरीका
नीचे दिए पैरामीटर:
- एक यूनीक आईडी, जो लोडर की पहचान करता है. इस उदाहरण में, आईडी
0
है. - लोडर को दिए जाने वाले वैकल्पिक आर्ग्युमेंट
कंस्ट्रक्शन (इस उदाहरण में
null
). - एक
LoaderManager.LoaderCallbacks
लागू करने पर, जोLoaderManager
कॉल, लोडर इवेंट की जानकारी देती हैं. इसमें उदाहरण के लिए, लोकल क्लासLoaderManager.LoaderCallbacks
इंटरफ़ेस को लागू करती है, ताकि वह रेफ़रंस पास कर सकेthis
ने खुद को.
initLoader()
कॉल से पक्का होता है कि
शुरू किया जाता है और चालू होता है. इसके दो संभावित नतीजे हो सकते हैं:
- अगर आईडी से तय किया गया लोडर पहले से मौजूद है, तो आखिरी बार बनाया गया लोडर का फिर से इस्तेमाल किया जाता है.
- अगर आईडी से तय किया गया लोडर मौजूद नहीं है,
initLoader()
ट्रिगरLoaderManager.LoaderCallbacks
तरीकाonCreateLoader()
. यहां पर आपको नया लोडर चलाने और उसे इंस्टैंशिएट करने के लिए कोड लागू करना होता है. ज़्यादा चर्चा के लिए,onCreateLoader
के बारे में सेक्शन देखें.
दोनों ही मामलों में, दी गई LoaderManager.LoaderCallbacks
लागू करने की प्रक्रिया, लोडर से जुड़ी होती है. इसे तब कॉल किया जाता है, जब
लोडर स्थिति में बदलाव. अगर, इस कॉल में, कॉल करने वाला व्यक्ति
शुरू कर दिया है और अनुरोध किया गया लोडर पहले से मौजूद है और
फिर सिस्टम onLoadFinished()
को कॉल करता है
initLoader()
के दौरान तुरंत. इसके लिए आपको तैयार रहना होगा. इस कॉलबैक के बारे में ज़्यादा चर्चा के लिए, के बारे में सेक्शन देखें
onLoadFinished
.
initLoader()
तरीका, बनाया गया Loader
दिखाता है.
लेकिन आपको इसके लिए कोई रेफ़रंस कैप्चर करने की ज़रूरत नहीं है. LoaderManager
,
को लोड करने की प्रोसेस अपने-आप ठीक हो जाती है. LoaderManager
ज़रूरत पड़ने पर, लोड होना शुरू हो जाता है और बंद हो जाता है. साथ ही, लोडर की स्थिति को बनाए रखता है
और उससे जुड़े कॉन्टेंट की शिकायत करें.
इसका मतलब है कि आप बहुत कम बार लोडर के साथ इंटरैक्ट करते हैं
सकता है.
लोड होने की प्रोसेस में दखल देने के लिए, आम तौर पर LoaderManager.LoaderCallbacks
तरीकों का इस्तेमाल किया जाता है
खास इवेंट के होने पर प्रोसेस करें. इस विषय पर ज़्यादा चर्चा के लिए, 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; }
LoaderManager कॉलबैक का इस्तेमाल करना
LoaderManager.LoaderCallbacks
एक कॉलबैक इंटरफ़ेस है
जिसकी मदद से क्लाइंट, LoaderManager
के साथ इंटरैक्ट कर सकता है.
खास तौर पर, CursorLoader
लोडर से
का डेटा सुरक्षित रखने में मदद करती है. इससे ऐप्लिकेशन,
गतिविधि या फ़्रैगमेंट के onStop()
और onStart()
वाले तरीके का डेटा होता है, ताकि
जब उपयोगकर्ता किसी ऐप्लिकेशन पर वापस लौटते हैं, तो उन्हें इसके लिए डेटा के
फिर से लोड करें.
नया लोडर बनाने का समय जानने और ऐप्लिकेशन को सही समय पर लोड होने की स्थिति बताने के लिए, LoaderManager.LoaderCallbacks
तरीके का इस्तेमाल किया जाता है
लोडर के डेटा का उपयोग बंद करने का समय होता है.
LoaderManager.LoaderCallbacks
में ये शामिल हैं
तरीका:
onCreateLoader()
: दिए गए आईडी के लिए, एक नयाLoader
इंस्टैंशिएट करता है और दिखाता है.
-
onLoadFinished()
: यह तब कॉल किया जाता है, जब पहले से बनाए गए लोडर का लोड होना पूरा हो जाता है.
onLoaderReset()
: तब कॉल किया जाता है जब पहले से बनाए गए लोडर को रीसेट किया जा रहा होता है, जिससे यह डेटा अनुपलब्ध.
नीचे दिए गए सेक्शन में, इन तरीकों के बारे में ज़्यादा जानकारी दी गई है.
ऑनCreateLoader
जब initLoader()
जैसी किसी लोडर को ऐक्सेस करने की कोशिश की जाती है, तो यह जांच की जाती है कि क्या
आईडी से तय किया गया लोडर मौजूद है. अगर ऐसा नहीं होता है, तो यह LoaderManager.LoaderCallbacks
तरीका onCreateLoader()
ट्रिगर करता है. यह
नया लोडर बनाया जाता है. आम तौर पर, यह एक CursorLoader
है, लेकिन आपके पास अपनी Loader
सब-क्लास लागू करने का विकल्प होता है.
नीचे दिए गए उदाहरण में, onCreateLoader()
कॉलबैक मेथड अपने कंस्ट्रक्टर का इस्तेमाल करके, एक CursorLoader
बनाता है.
ContentProvider
पर कोई क्वेरी करने के लिए, जानकारी के पूरे सेट की ज़रूरत होती है. खास तौर पर, इसे इनकी ज़रूरत होती है:
- uri: कॉन्टेंट को वापस पाने के लिए यूआरआई.
- प्रोजेक्शन: लौटाए जाने वाले कॉलम की सूची. पासिंग
null
सभी कॉलम दिखाता है, जो कि अच्छी तरह काम नहीं करते. - चुनना: ऐसा फ़िल्टर जो बताता है कि कौनसी लाइन देखनी है,
SQL WHERE क्लॉज़ के तौर पर फ़ॉर्मैट किया गया हो (इसमें WHERE को छोड़कर). पासिंग
null
दिए गए यूआरआई के लिए सभी पंक्तियां दिखाता है. - selectionArgs: चुनाव में ?s को शामिल करने पर, उनकी जगह selectionArgs की वैल्यू उसी क्रम में हैं, जिस क्रम में वे चुनें. वैल्यू, स्ट्रिंग के तौर पर बाउंड होती हैं.
- sortOrder: एसक्यूएल के फ़ॉर्मैट में पंक्तियों को कैसे ऑर्डर करें
ORDER BY क्लॉज़ (ऑर्डर 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"); }
onLoadFinish किया गया
यह तरीका तब कॉल किया जाता है, जब पहले से बनाया गया लोडर अपना लोड पूरा कर लेता है. इस बात की गारंटी है कि पिछले डेटा की रिलीज़ से पहले इस तरीके को कॉल किया जाएगा जो इस लोडर के लिए दी गई है. इस स्थिति में, पुराना डेटा हटा दिया, क्योंकि वे रिलीज़ होने ही वाले हैं. हालाँकि, अपने संस्थान के डेटा को लोडर का मालिक होता है और वह इसका ध्यान रखता है.
ऐप्लिकेशन बंद होने के बाद, लोडर डेटा को रिलीज़ कर देता है
उसका इस्तेमाल करना. उदाहरण के लिए, अगर डेटा, 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); }
ऑनलोडर रीसेट
यह तरीका तब कॉल किया जाता है, जब पहले से बनाए गए लोडर को रीसेट किया जा रहा हो, इसलिए डेटा उपलब्ध नहीं करा सके. इस कॉलबैक से आपको पता चलता है कि डेटा कब रिलीज़ होने वाला है, ताकि आप अपना संदर्भ हटा सकें.
लागू करने की यह प्रक्रिया,
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: इसमें, संख्या कम करने के लिए थ्रॉटलिंग इस्तेमाल करने के तरीके का उदाहरण दिया गया है उन क्वेरी का जवाब देता है जो कॉन्टेंट उपलब्ध कराने वाला संगठन डेटा में बदलाव होने पर करता है.