page.title=Handling the Results trainingnavtop=true startpage=true @jd:body <!-- This is the training bar --> <div id="tb-wrapper"> <div id="tb"> <h2>This lesson teaches you to</h2> <ol> <li> <a href="#HandleResults">Handle Query Results</a> </li> <li> <a href="#HandleReset">Delete Old Cursor References</a></li> </ol> <h2>Try it out</h2> <div class="download-box"> <a href="{@docRoot}shareables/training/ThreadSample.zip" class="button">Download the sample</a> <p class="filename">ThreadSample.zip</p> </div> </div> </div> <p> As shown in the previous lesson, you should begin loading your data with a {@link android.support.v4.content.CursorLoader} in your implementation of {@link android.support.v4.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()}. The loader then provides the query results to your {@link android.app.Activity} or {@link android.support.v4.app.FragmentActivity} in your implementation of {@link android.support.v4.app.LoaderManager.LoaderCallbacks#onLoadFinished LoaderCallbacks.onLoadFinished()}. One of the incoming arguments to this method is a {@link android.database.Cursor} containing the query results. You can use this object to update your data display or do further processing. </p> <p> Besides {@link android.support.v4.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()} and {@link android.support.v4.app.LoaderManager.LoaderCallbacks#onLoadFinished onLoadFinished()}, you also have to implement {@link android.support.v4.app.LoaderManager.LoaderCallbacks#onLoaderReset onLoaderReset()}. This method is invoked when {@link android.support.v4.content.CursorLoader} detects that data associated with the {@link android.database.Cursor} has changed. When the data changes, the framework also re-runs the current query. </p> <h2 id="HandleResults">Handle Query Results</h2> <p> To display {@link android.database.Cursor} data returned by {@link android.support.v4.content.CursorLoader}, use a {@link android.view.View} class that implements {@link android.widget.AdapterView} and provide the view with an adapter that implements {@link android.support.v4.widget.CursorAdapter}. The system then automatically moves data from the {@link android.database.Cursor} to the view. </p> <p> You can set up the linkage between the view and adapter before you have any data to display, and then move a {@link android.database.Cursor} into the adapter in the {@link android.support.v4.app.LoaderManager.LoaderCallbacks#onLoadFinished onLoadFinished()} method. As soon as you move the {@link android.database.Cursor} into the adapter, the system automatically updates the view. This also happens if you change the contents of the {@link android.database.Cursor}. </p> <p> For example: </p> <pre> public String[] mFromColumns = { DataProviderContract.IMAGE_PICTURENAME_COLUMN }; public int[] mToFields = { R.id.PictureName }; // Gets a handle to a List View ListView mListView = (ListView) findViewById(R.id.dataList); /* * Defines a SimpleCursorAdapter for the ListView * */ SimpleCursorAdapter mAdapter = new SimpleCursorAdapter( this, // Current context R.layout.list_item, // Layout for a single row null, // No Cursor yet mFromColumns, // Cursor columns to use mToFields, // Layout fields to use 0 // No flags ); // Sets the adapter for the view mListView.setAdapter(mAdapter); ... /* * Defines the callback that {@link android.support.v4.content.CursorLoader} calls * when it's finished its query */ @Override public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { ... /* * Moves the query results into the adapter, causing the * ListView fronting this adapter to re-display */ mAdapter.changeCursor(cursor); } </pre> <h2 id="HandleReset">Delete Old Cursor References</h2> <p> The {@link android.support.v4.content.CursorLoader} is reset whenever its {@link android.database.Cursor} becomes invalid. This usually occurs because the data associated with the {@link android.database.Cursor} has changed. Before re-running the query, the framework calls your implementation of {@link android.support.v4.app.LoaderManager.LoaderCallbacks#onLoaderReset onLoaderReset()}. In this callback, you should delete all references to the current {@link android.database.Cursor} in order to prevent memory leaks. Once {@link android.support.v4.app.LoaderManager.LoaderCallbacks#onLoaderReset onLoaderReset()} finishes, {@link android.support.v4.content.CursorLoader} re-runs its query. </p> <p> For example: </p> <pre> /* * Invoked when the CursorLoader is being reset. For example, this is * called if the data in the provider changes and the Cursor becomes stale. */ @Override public void onLoaderReset(Loader<Cursor> loader) { /* * Clears out the adapter's reference to the Cursor. * This prevents memory leaks. */ mAdapter.changeCursor(null); } </pre>