1 page.title=Aktivitas 2 parent.title=Loader 3 parent.link=activities.html 4 @jd:body 5 <div id="qv-wrapper"> 6 <div id="qv"> 7 <h2>Dalam dokumen ini</h2> 8 <ol> 9 <li><a href="#summary">Rangkuman Loader API</a></li> 10 <li><a href="#app">Menggunakan Loader dalam Aplikasi</a> 11 <ol> 12 <li><a href="#requirements"></a></li> 13 <li><a href="#starting">Memulai Loader</a></li> 14 <li><a href="#restarting">Me-restart Loader</a></li> 15 <li><a href="#callback">Menggunakan Callback LoaderManager</a></li> 16 </ol> 17 </li> 18 <li><a href="#example">Contoh</a> 19 <ol> 20 <li><a href="#more_examples">Contoh Selengkapnya</a></li> 21 </ol> 22 </li> 23 </ol> 24 25 <h2>Kelas-kelas utama</h2> 26 <ol> 27 <li>{@link android.app.LoaderManager}</li> 28 <li>{@link android.content.Loader}</li> 29 30 </ol> 31 32 <h2>Contoh-contoh terkait</h2> 33 <ol> 34 <li> <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LoaderCursor.html"> 35 LoaderCursor</a></li> 36 <li> <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LoaderThrottle.html"> 37 LoaderThrottle</a></li> 38 </ol> 39 </div> 40 </div> 41 42 <p>Diperkenalkan di Android 3.0, loader memudahkan pemuatan data asinkron 43 dalam aktivitas atau fragmen. Loader memiliki karakteristik ini:</p> 44 <ul> 45 <li>Loader tersedia untuk setiap {@link android.app.Activity} dan {@link 46 android.app.Fragment}.</li> 47 <li>Loader menyediakan pemuatan data asinkron.</li> 48 <li>Loader memantau sumber data mereka dan memberikan hasil baru bila 49 konten berubah.</li> 50 <li>Loader secara otomatis menghubungkan kembali ke kursor loader lalu saat 51 dibuat kembali setelah perubahan konfigurasi. Karena itu, loader tidak perlu melakukan query ulang 52 datanya.</li> 53 </ul> 54 55 <h2 id="summary">Rangkuman Loader API</h2> 56 57 <p>Ada beberapa kelas dan antarmuka yang mungkin dilibatkan dalam menggunakan 58 loader pada aplikasi. Semuanya dirangkum dalam tabel ini:</p> 59 60 <table> 61 <tr> 62 <th>Kelas/Antarmuka</th> 63 <th>Keterangan</th> 64 </tr> 65 <tr> 66 <td>{@link android.app.LoaderManager}</td> 67 <td>Kelas abstrak yang dikaitkan dengan {@link android.app.Activity} atau 68 {@link android.app.Fragment} untuk mengelola satu atau beberapa instance {@link 69 android.content.Loader}.Ini membantu aplikasi mengelola 70 operasi berjalan lebih lama bersamaan dengan daur hidup {@link android.app.Activity} 71 atau {@link android.app.Fragment}; penggunaan paling umumnya adalah dengan 72 {@link android.content.CursorLoader}, akan tetapi aplikasi bebas menulis loader-nya 73 sendiri untuk memuat tipe data lainnya. 74 <br /> 75 <br /> 76 Hanya ada satu {@link android.app.LoaderManager} per aktivitas atau fragmen. Namun {@link android.app.LoaderManager} bisa memiliki 77 beberapa loader.</td> 78 </tr> 79 <tr> 80 <td>{@link android.app.LoaderManager.LoaderCallbacks}</td> 81 <td>Antarmuka callback untuk klien berinteraksi dengan {@link 82 android.app.LoaderManager}. Misalnya, Anda menggunakan metode callback {@link 83 android.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()} 84 untuk membuat loader baru.</td> 85 </tr> 86 <tr> 87 <td>{@link android.content.Loader}</td> 88 <td>Kelas abstrak yang melakukan pemuatan data asinkron. Ini 89 adalah kelas dasar untuk loader. Biasanya Anda akan menggunakan {@link 90 android.content.CursorLoader}, namun Anda bisa menerapkan subkelas sendiri. Selagi 91 loader aktif, loader harus memantau sumber datanya dan memberikan hasil 92 baru bila konten berubah. </td> 93 </tr> 94 <tr> 95 <td>{@link android.content.AsyncTaskLoader}</td> 96 <td>Loader abstrak yang menyediakan {@link android.os.AsyncTask} untuk melakukan pekerjaan.</td> 97 </tr> 98 <tr> 99 <td>{@link android.content.CursorLoader}</td> 100 <td>Subkelas {@link android.content.AsyncTaskLoader} yang meng-query 101 {@link android.content.ContentResolver} dan mengembalikan {@link 102 android.database.Cursor}. Kelas ini mengimplementasikan protokol {@link 103 android.content.Loader} dengan cara standar untuk query kursor, 104 yang dibuat berdasarkan {@link android.content.AsyncTaskLoader} untuk melakukan query kursor 105 pada thread latar belakang agar tidak memblokir UI aplikasi. Menggunakan loader 106 ini merupakan cara terbaik untuk memuat data secara asinkron dari {@link 107 android.content.ContentProvider}, sebagai ganti melakukan query terkelola melalui 108 fragmen atau API aktivitas.</td> 109 </tr> 110 </table> 111 112 <p>Kelas dan antarmuka dalam tabel di atas merupakan komponen 113 esensial yang akan Anda gunakan untuk mengimplementasikan loader dalam aplikasi Anda. Anda tidak memerlukan semuanya 114 untuk setiap loader yang dibuat, namun Anda akan selalu memerlukan acuan ke {@link 115 android.app.LoaderManager} untuk memulai loader dan implementasi 116 kelas {@link android.content.Loader} seperti {@link 117 android.content.CursorLoader}. Bagian berikut ini menunjukkan kepada Anda cara menggunakan 118 kelas dan antarmuka ini dalam aplikasi.</p> 119 120 <h2 id ="app">Menggunakan Loader dalam Aplikasi</h2> 121 <p>Bagian ini menjelaskan cara menggunakan loader dalam aplikasi Android. Aplikasi 122 yang menggunakan loader biasanya berisi yang berikut ini:</p> 123 <ul> 124 <li>{@link android.app.Activity} atau {@link android.app.Fragment}.</li> 125 <li>Instance {@link android.app.LoaderManager}.</li> 126 <li>{@link android.content.CursorLoader} akan memuat data yang didukung oleh {@link 127 android.content.ContentProvider}. Atau, Anda dapat mengimplementasikan subkelas sendiri 128 dari {@link android.content.Loader} atau {@link android.content.AsyncTaskLoader} untuk 129 memuat data dari beberapa sumber lain.</li> 130 <li>Implementasi untuk {@link android.app.LoaderManager.LoaderCallbacks}. 131 Di sinilah Anda membuat loader baru dan mengelola acuan bagi loader 132 yang ada.</li> 133 <li>Cara menampilkan data loader, seperti {@link 134 android.widget.SimpleCursorAdapter}.</li> 135 <li>Sumber data, seperti {@link android.content.ContentProvider}, saat menggunakan 136 {@link android.content.CursorLoader}.</li> 137 </ul> 138 <h3 id="starting">Memulai Loader</h3> 139 140 <p>{@link android.app.LoaderManager} mengelola satu atau beberapa instance {@link 141 android.content.Loader} dalam {@link android.app.Activity} atau 142 {@link android.app.Fragment}. Hanya ada satu {@link 143 android.app.LoaderManager} per aktivitas atau fragmen.</p> 144 145 <p>Anda biasanya 146 memulai {@link android.content.Loader} dalam metode {@link 147 android.app.Activity#onCreate onCreate()} aktivitas, atau dalam metode 148 {@link android.app.Fragment#onActivityCreated onActivityCreated()} fragmen. Anda 149 melakukannya dengan cara berikut ini:</p> 150 151 <pre>// Prepare the loader. Either re-connect with an existing one, 152 // or start a new one. 153 getLoaderManager().initLoader(0, null, this);</pre> 154 155 <p>Metode {@link android.app.LoaderManager#initLoader initLoader()} mengambil 156 parameter berikut:</p> 157 <ul> 158 <li>ID unik yang mengidentifikasi loader. Dalam contoh ini, ID-nya adalah 0.</li> 159 <li>Argumen opsional untuk dipasok ke loader 160 pada saat pembuatan (dalam contoh ini <code>null</code>).</li> 161 162 <li>Implementasi {@link android.app.LoaderManager.LoaderCallbacks}, yang 163 akan dipanggil {@link android.app.LoaderManager} untuk melaporkan kejadian loader. Dalam contoh 164 ini, kelas lokal mengimplementasikan antarmuka {@link 165 android.app.LoaderManager.LoaderCallbacks}, sehingga meneruskan acuan 166 ke dirinya sendiri, {@code this}.</li> 167 </ul> 168 <p>Panggilan {@link android.app.LoaderManager#initLoader initLoader()} memastikan bahwa loader 169 telah dimulai dan aktif. Ia memiliki dua kemungkinan hasil:</p> 170 <ul> 171 <li>Jika loader yang disebutkan oleh ID sudah ada, loader yang dibuat terakhir akan digunakan 172 kembali.</li> 173 <li>Jika loader yang disebutkan oleh ID <em>tidak</em> ada, 174 {@link android.app.LoaderManager#initLoader initLoader()} akan memicu metode 175 {@link android.app.LoaderManager.LoaderCallbacks} {@link android.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()}. 176 Di sinilah Anda mengimplementasikan kode untuk membuat instance dan mengembalikan loader baru. 177 Untuk diskusi selengkapnya, lihat bagian <a href="#onCreateLoader">onCreateLoader</a>.</li> 178 </ul> 179 <p>Dalam hal ini, implementasi {@link android.app.LoaderManager.LoaderCallbacks} 180 yang ditentukan akan dikaitkan dengan loader, dan akan dipanggil bila 181 status loader berubah. Jika saat panggilan ini status pemanggil sudah 182 dimulai, dan loader yang diminta sudah ada dan telah menghasilkan 183 datanya, maka sistem segera memanggil {@link 184 android.app.LoaderManager.LoaderCallbacks#onLoadFinished onLoadFinished()} 185 (selama {@link android.app.LoaderManager#initLoader initLoader()}), 186 sehingga Anda harus siap bila hal ini terjadi. Lihat <a href="#onLoadFinished"> 187 onLoadFinished</a> untuk diskusi selengkapnya mengenai callback ini</p> 188 189 <p>Perhatikan bahwa metode {@link android.app.LoaderManager#initLoader initLoader()} 190 mengembalikan {@link android.content.Loader} yang dibuat, namun Anda tidak 191 perlu menangkap acuan ke sana. {@link android.app.LoaderManager} mengelola 192 masa hidup loader secara otomatis. {@link android.app.LoaderManager} 193 memulai dan menghentikan pemuatan jika perlu, dan menjaga status loader 194 dan konten terkaitnya. Seperti yang tersirat di sini, Anda akan jarang berinteraksi dengan loader 195 secara langsung (meskipun misalnya menggunakan metode loader untuk menyempurnakan perilaku 196 loader, lihat contoh <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LoaderThrottle.html"> LoaderThrottle</a>). 197 Anda paling sering akan menggunakan metode {@link 198 android.app.LoaderManager.LoaderCallbacks} untuk mengintervensi proses 199 pemuatan saat terjadi kejadian tertentu. Untuk diskusi selengkapnya mengenai topik ini, lihat <a href="#callback">Menggunakan Callback LoaderManager</a>.</p> 200 201 <h3 id="restarting">Me-restart Loader</h3> 202 203 <p>Bila Anda menggunakan {@link android.app.LoaderManager#initLoader initLoader()}, seperti 204 ditampilkan di atas, loader yang ada akan digunakan dengan ID yang ditetapkan jika ada. 205 Jika tidak ada, ID akan dibuat. Namun kadang-kadang Anda perlu membuang data lama 206 dan mulai dari awal.</p> 207 208 <p>Untuk membuang data lama, gunakan {@link 209 android.app.LoaderManager#restartLoader restartLoader()}. Misalnya, implementasi 210 {@link android.widget.SearchView.OnQueryTextListener} ini akan me-restart 211 bila query pengguna berubah. Loader perlu di-restart 212 agar dapat menggunakan filter pencarian yang telah direvisi untuk melakukan query baru:</p> 213 214 <pre> 215 public boolean onQueryTextChanged(String newText) { 216 // Called when the action bar search text has changed. Update 217 // the search filter, and restart the loader to do a new query 218 // with this filter. 219 mCurFilter = !TextUtils.isEmpty(newText) ? newText : null; 220 getLoaderManager().restartLoader(0, null, this); 221 return true; 222 }</pre> 223 224 <h3 id="callback">Menggunakan Callback LoaderManager</h3> 225 226 <p>{@link android.app.LoaderManager.LoaderCallbacks} adalah antarmuka callback 227 yang memungkinkan klien berinteraksi dengan {@link android.app.LoaderManager}. </p> 228 <p>Loader, khususnya {@link android.content.CursorLoader}, diharapkan 229 mempertahankan datanya setelah dihentikan. Ini memungkinkan aplikasi mempertahankan 230 datanya di aktivitas atau metode {@link android.app.Activity#onStop 231 onStop()} fragmen dan {@link android.app.Activity#onStart onStart()}, sehingga 232 bila pengguna kembali ke aplikasi, mereka tidak harus menunggu data 233 dimuat kembali. Anda menggunakan metode {@link android.app.LoaderManager.LoaderCallbacks} 234 untuk mengetahui waktu membuat loader baru, dan memberi tahu aplikasi kapan 235 berhenti menggunakan data loader.</p> 236 237 <p>{@link android.app.LoaderManager.LoaderCallbacks} berisi metode 238 ini:</p> 239 <ul> 240 <li>{@link android.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()} 241 Membuat instance dan mengembalikan {@link android.content.Loader} baru untuk ID yang diberikan. 242 </li></ul> 243 <ul> 244 <li> {@link android.app.LoaderManager.LoaderCallbacks#onLoadFinished onLoadFinished()} 245 Dipanggil bila loader yang dibuat sebelumnya selesai dimuat. 246 </li></ul> 247 <ul> 248 <li>{@link android.app.LoaderManager.LoaderCallbacks#onLoaderReset onLoaderReset()} 249 Dipanggil bila loader yang dibuat sebelumnya sedang di-reset, sehingga datanya 250 tidak tersedia. 251 </li> 252 </ul> 253 <p>Metode ini dijelaskan lebih detail dalam bagian berikutnya.</p> 254 255 <h4 id ="onCreateLoader">onCreateLoader</h4> 256 257 <p>Saat Anda mencoba mengakses loader (misalnya, melalui {@link 258 android.app.LoaderManager#initLoader initLoader()}), ia akan memeriksa untuk mengetahui adanya 259 loader yang ditetapkan oleh ID. Jika tidak ada, ia akan memicu metode {@link 260 android.app.LoaderManager.LoaderCallbacks} {@link 261 android.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()}. Di 262 sinilah Anda membuat loader baru. Biasanya ini adalah {@link 263 android.content.CursorLoader}, namun Anda bisa mengimplementasikan sendiri subkelas {@link 264 android.content.Loader}. </p> 265 266 <p>Dalam contoh ini, metode callback {@link 267 android.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()} 268 akan membuat {@link android.content.CursorLoader}. Anda harus membuat 269 {@link android.content.CursorLoader} menggunakan metode konstruktornya, yang 270 memerlukan set informasi lengkap untuk melakukan query ke {@link 271 android.content.ContentProvider}. Secara khusus, ia memerlukan:</p> 272 <ul> 273 <li><em>uri</em> URI untuk konten yang akan diambil. </li> 274 <li><em>projection</em> Daftar berisi kolom yang akan dikembalikan. Meneruskan 275 <code>null</code> akan mengembalikan semua kolom, jadi tidak efisien. </li> 276 <li><em>selection</em> Filter yang mendeklarasikan baris yang akan dikembalikan, 277 diformat sebagai klausa SQL WHERE (tidak termasuk WHERE itu sendiri). Meneruskan 278 <code>null</code> akan mengembalikan semua baris untuk URI yang diberikan. </li> 279 <li><em>selectionArgs</em> Anda dapat menyertakan ?s dalam pilihan, yang akan 280 digantikan dengan nilai dari <em>selectionArgs</em>, agar muncul dalam 281 pilihan. Nilai-nilai akan diikat sebagai String. </li> 282 <li><em>sortOrder</em> Cara menyusun baris, diformat sebagai klausa SQL 283 ORDER BY (tidak termasuk ORDER BY itu sendiri). Meneruskan <code>null</code> akan 284 menggunakan urutan sortir default, yang mungkin tidak berurutan.</li> 285 </ul> 286 <p>Misalnya:</p> 287 <pre> 288 // If non-null, this is the current filter the user has provided. 289 String mCurFilter; 290 ... 291 public Loader<Cursor> onCreateLoader(int id, Bundle args) { 292 // This is called when a new Loader needs to be created. This 293 // sample only has one Loader, so we don't care about the ID. 294 // First, pick the base URI to use depending on whether we are 295 // currently filtering. 296 Uri baseUri; 297 if (mCurFilter != null) { 298 baseUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI, 299 Uri.encode(mCurFilter)); 300 } else { 301 baseUri = Contacts.CONTENT_URI; 302 } 303 304 // Now create and return a CursorLoader that will take care of 305 // creating a Cursor for the data being displayed. 306 String select = "((" + Contacts.DISPLAY_NAME + " NOTNULL) AND (" 307 + Contacts.HAS_PHONE_NUMBER + "=1) AND (" 308 + Contacts.DISPLAY_NAME + " != '' ))"; 309 return new CursorLoader(getActivity(), baseUri, 310 CONTACTS_SUMMARY_PROJECTION, select, null, 311 Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC"); 312 }</pre> 313 <h4 id="onLoadFinished">onLoadFinished</h4> 314 315 <p>Metode ini dipanggil bila loader yang dibuat sebelumnya selesai dimuat. 316 Metode ini dijamin dipanggil sebelum pelepasan data terakhir 317 yang disediakan untuk loader ini. Di titik ini Anda harus menyingkirkan semua penggunaan 318 data lama (karena akan segera dilepas), namun jangan melepas sendiri 319 data tersebut karena loader memilikinya dan akan menanganinya.</p> 320 321 322 <p>Loader akan melepas data setelah mengetahui bahwa aplikasi tidak 323 lagi menggunakannya. Misalnya, jika data adalah kursor dari {@link 324 android.content.CursorLoader}, Anda tidak boleh memanggil {@link 325 android.database.Cursor#close close()} sendiri. Jika kursor ditempatkan 326 dalam {@link android.widget.CursorAdapter}, Anda harus menggunakan metode {@link 327 android.widget.SimpleCursorAdapter#swapCursor swapCursor()} agar 328 {@link android.database.Cursor} lama tidak ditutup. Misalnya:</p> 329 330 <pre> 331 // This is the Adapter being used to display the list's data.<br 332 />SimpleCursorAdapter mAdapter; 333 ... 334 335 public void onLoadFinished(Loader<Cursor> loader, Cursor data) { 336 // Swap the new cursor in. (The framework will take care of closing the 337 // old cursor once we return.) 338 mAdapter.swapCursor(data); 339 }</pre> 340 341 <h4 id="onLoaderReset">onLoaderReset</h4> 342 343 <p>Metode ini dipanggil bila loader yang dibuat sebelumnya sedang di-reset, sehingga datanya 344 tidak tersedia. Callback ini memungkinkan Anda mengetahui 345 kapan data akan dilepas sehingga dapat menghapus acuannya ke callback. </p> 346 <p>Implementasi ini memanggil 347 {@link android.widget.SimpleCursorAdapter#swapCursor swapCursor()} 348 dengan nilai <code>null</code>:</p> 349 350 <pre> 351 // This is the Adapter being used to display the list's data. 352 SimpleCursorAdapter mAdapter; 353 ... 354 355 public void onLoaderReset(Loader<Cursor> loader) { 356 // This is called when the last Cursor provided to onLoadFinished() 357 // above is about to be closed. We need to make sure we are no 358 // longer using it. 359 mAdapter.swapCursor(null); 360 }</pre> 361 362 363 <h2 id="example">Contoh</h2> 364 365 <p>Sebagai contoh, berikut ini adalah implementasi penuh {@link 366 android.app.Fragment} yang menampilkan {@link android.widget.ListView} berisi 367 hasil query terhadap penyedia konten kontak. Ia menggunakan {@link 368 android.content.CursorLoader} untuk mengelola query pada penyedia.</p> 369 370 <p>Agar aplikasi dapat mengakses kontak pengguna, seperti yang ditampilkan dalam contoh ini, 371 manifesnya harus menyertakan izin 372 {@link android.Manifest.permission#READ_CONTACTS READ_CONTACTS}.</p> 373 374 <pre> 375 public static class CursorLoaderListFragment extends ListFragment 376 implements OnQueryTextListener, LoaderManager.LoaderCallbacks<Cursor> { 377 378 // This is the Adapter being used to display the list's data. 379 SimpleCursorAdapter mAdapter; 380 381 // If non-null, this is the current filter the user has provided. 382 String mCurFilter; 383 384 @Override public void onActivityCreated(Bundle savedInstanceState) { 385 super.onActivityCreated(savedInstanceState); 386 387 // Give some text to display if there is no data. In a real 388 // application this would come from a resource. 389 setEmptyText("No phone numbers"); 390 391 // We have a menu item to show in action bar. 392 setHasOptionsMenu(true); 393 394 // Create an empty adapter we will use to display the loaded data. 395 mAdapter = new SimpleCursorAdapter(getActivity(), 396 android.R.layout.simple_list_item_2, null, 397 new String[] { Contacts.DISPLAY_NAME, Contacts.CONTACT_STATUS }, 398 new int[] { android.R.id.text1, android.R.id.text2 }, 0); 399 setListAdapter(mAdapter); 400 401 // Prepare the loader. Either re-connect with an existing one, 402 // or start a new one. 403 getLoaderManager().initLoader(0, null, this); 404 } 405 406 @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { 407 // Place an action bar item for searching. 408 MenuItem item = menu.add("Search"); 409 item.setIcon(android.R.drawable.ic_menu_search); 410 item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); 411 SearchView sv = new SearchView(getActivity()); 412 sv.setOnQueryTextListener(this); 413 item.setActionView(sv); 414 } 415 416 public boolean onQueryTextChange(String newText) { 417 // Called when the action bar search text has changed. Update 418 // the search filter, and restart the loader to do a new query 419 // with this filter. 420 mCurFilter = !TextUtils.isEmpty(newText) ? newText : null; 421 getLoaderManager().restartLoader(0, null, this); 422 return true; 423 } 424 425 @Override public boolean onQueryTextSubmit(String query) { 426 // Don't care about this. 427 return true; 428 } 429 430 @Override public void onListItemClick(ListView l, View v, int position, long id) { 431 // Insert desired behavior here. 432 Log.i("FragmentComplexList", "Item clicked: " + id); 433 } 434 435 // These are the Contacts rows that we will retrieve. 436 static final String[] CONTACTS_SUMMARY_PROJECTION = new String[] { 437 Contacts._ID, 438 Contacts.DISPLAY_NAME, 439 Contacts.CONTACT_STATUS, 440 Contacts.CONTACT_PRESENCE, 441 Contacts.PHOTO_ID, 442 Contacts.LOOKUP_KEY, 443 }; 444 public Loader<Cursor> onCreateLoader(int id, Bundle args) { 445 // This is called when a new Loader needs to be created. This 446 // sample only has one Loader, so we don't care about the ID. 447 // First, pick the base URI to use depending on whether we are 448 // currently filtering. 449 Uri baseUri; 450 if (mCurFilter != null) { 451 baseUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI, 452 Uri.encode(mCurFilter)); 453 } else { 454 baseUri = Contacts.CONTENT_URI; 455 } 456 457 // Now create and return a CursorLoader that will take care of 458 // creating a Cursor for the data being displayed. 459 String select = "((" + Contacts.DISPLAY_NAME + " NOTNULL) AND (" 460 + Contacts.HAS_PHONE_NUMBER + "=1) AND (" 461 + Contacts.DISPLAY_NAME + " != '' ))"; 462 return new CursorLoader(getActivity(), baseUri, 463 CONTACTS_SUMMARY_PROJECTION, select, null, 464 Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC"); 465 } 466 467 public void onLoadFinished(Loader<Cursor> loader, Cursor data) { 468 // Swap the new cursor in. (The framework will take care of closing the 469 // old cursor once we return.) 470 mAdapter.swapCursor(data); 471 } 472 473 public void onLoaderReset(Loader<Cursor> loader) { 474 // This is called when the last Cursor provided to onLoadFinished() 475 // above is about to be closed. We need to make sure we are no 476 // longer using it. 477 mAdapter.swapCursor(null); 478 } 479 }</pre> 480 <h3 id="more_examples">Contoh Selengkapnya</h3> 481 482 <p>Ada beberapa contoh berbeda dalam <strong>ApiDemos</strong> yang 483 mengilustrasikan cara menggunakan loader:</p> 484 <ul> 485 <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LoaderCursor.html"> 486 LoaderCursor</a> Versi lengkap dari 487 cuplikan yang ditampilkan di atas.</li> 488 <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LoaderThrottle.html"> LoaderThrottle</a> Contoh cara penggunaan throttling untuk 489 mengurangi jumlah query dari penyedia konten saat datanya berubah.</li> 490 </ul> 491 492 <p>Untuk informasi tentang mengunduh dan menginstal contoh SDK, lihat <a href="http://developer.android.com/resources/samples/get.html"> Mendapatkan 493 Contoh</a>. </p> 494 495