| Joe Malin | ba34f09 | 2012-11-05 17:22:24 -0800 | [diff] [blame] | 1 | page.title=Handling the Results |
| 2 | trainingnavtop=true |
| 3 | startpage=true |
| 4 | |
| 5 | @jd:body |
| 6 | |
| 7 | <!-- This is the training bar --> |
| 8 | <div id="tb-wrapper"> |
| 9 | <div id="tb"> |
| 10 | <h2>This lesson teaches you to</h2> |
| 11 | <ol> |
| 12 | <li> |
| 13 | <a href="#HandleResults">Handle Query Results</a> |
| 14 | </li> |
| 15 | <li> |
| 16 | <a href="#HandleReset">Delete Old Cursor References</a></li> |
| 17 | </ol> |
| 18 | |
| 19 | <h2>Try it out</h2> |
| 20 | <div class="download-box"> |
| 21 | <a href="{@docRoot}shareables/training/ThreadSample.zip" class="button">Download the sample</a> |
| 22 | <p class="filename">ThreadSample.zip</p> |
| 23 | </div> |
| 24 | |
| 25 | </div> |
| 26 | </div> |
| 27 | |
| 28 | <p> |
| 29 | As shown in the previous lesson, you should begin loading your data with a |
| 30 | {@link android.support.v4.content.CursorLoader} in your implementation of |
| 31 | {@link android.support.v4.app.LoaderManager.LoaderCallbacks#onCreateLoader |
| 32 | onCreateLoader()}. The loader then provides the query results to your |
| 33 | {@link android.app.Activity} or {@link android.support.v4.app.FragmentActivity} in your |
| 34 | implementation of {@link android.support.v4.app.LoaderManager.LoaderCallbacks#onLoadFinished |
| 35 | LoaderCallbacks.onLoadFinished()}. One of the incoming arguments to this method is a |
| 36 | {@link android.database.Cursor} containing the query results. You can use this object to |
| 37 | update your data display or do further processing. |
| 38 | </p> |
| 39 | <p> |
| 40 | Besides |
| 41 | {@link android.support.v4.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()} and |
| 42 | {@link android.support.v4.app.LoaderManager.LoaderCallbacks#onLoadFinished onLoadFinished()}, |
| 43 | you also have to implement |
| 44 | {@link android.support.v4.app.LoaderManager.LoaderCallbacks#onLoaderReset onLoaderReset()}. |
| 45 | This method is invoked when {@link android.support.v4.content.CursorLoader} detects |
| 46 | that data associated with the {@link android.database.Cursor} has changed. When the |
| 47 | data changes, the framework also re-runs the current query. |
| 48 | </p> |
| 49 | <h2 id="HandleResults">Handle Query Results</h2> |
| 50 | <p> |
| 51 | To display {@link android.database.Cursor} data returned by |
| 52 | {@link android.support.v4.content.CursorLoader}, use a |
| 53 | {@link android.view.View} class that implements {@link android.widget.AdapterView} and |
| 54 | provide the view with an adapter that implements |
| 55 | {@link android.support.v4.widget.CursorAdapter}. The system then automatically moves data from |
| 56 | the {@link android.database.Cursor} to the view. |
| 57 | </p> |
| 58 | <p> |
| 59 | You can set up the linkage between the view and adapter before you have any data to display, |
| 60 | and then move a {@link android.database.Cursor} into the adapter in the |
| 61 | {@link android.support.v4.app.LoaderManager.LoaderCallbacks#onLoadFinished onLoadFinished()} |
| 62 | method. As soon as you move the {@link android.database.Cursor} into the adapter, the |
| 63 | system automatically updates the view. This also happens if you change the contents of the |
| 64 | {@link android.database.Cursor}. |
| 65 | </p> |
| 66 | <p> |
| 67 | For example: |
| 68 | </p> |
| 69 | <pre> |
| 70 | public String[] mFromColumns = { |
| 71 | DataProviderContract.IMAGE_PICTURENAME_COLUMN |
| 72 | }; |
| 73 | public int[] mToFields = { |
| 74 | R.id.PictureName |
| 75 | }; |
| 76 | // Gets a handle to a List View |
| 77 | ListView mListView = (ListView) findViewById(R.id.dataList); |
| 78 | /* |
| 79 | * Defines a SimpleCursorAdapter for the ListView |
| 80 | * |
| 81 | */ |
| 82 | SimpleCursorAdapter mAdapter = |
| 83 | new SimpleCursorAdapter( |
| 84 | this, // Current context |
| 85 | R.layout.list_item, // Layout for a single row |
| 86 | null, // No Cursor yet |
| 87 | mFromColumns, // Cursor columns to use |
| 88 | mToFields, // Layout fields to use |
| 89 | 0 // No flags |
| 90 | ); |
| 91 | // Sets the adapter for the view |
| 92 | mListView.setAdapter(mAdapter); |
| 93 | ... |
| 94 | /* |
| 95 | * Defines the callback that {@link android.support.v4.content.CursorLoader} calls |
| 96 | * when it's finished its query |
| 97 | */ |
| 98 | @Override |
| 99 | public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { |
| 100 | ... |
| 101 | /* |
| 102 | * Moves the query results into the adapter, causing the |
| 103 | * ListView fronting this adapter to re-display |
| 104 | */ |
| 105 | mAdapter.changeCursor(cursor); |
| 106 | } |
| 107 | </pre> |
| 108 | <h2 id="HandleReset">Delete Old Cursor References</h2> |
| 109 | <p> |
| 110 | The {@link android.support.v4.content.CursorLoader} is reset whenever its |
| 111 | {@link android.database.Cursor} becomes invalid. This usually occurs because the data associated |
| 112 | with the {@link android.database.Cursor} has changed. Before re-running the query, |
| 113 | the framework calls your implementation of |
| 114 | {@link android.support.v4.app.LoaderManager.LoaderCallbacks#onLoaderReset onLoaderReset()}. In |
| 115 | this callback, you should delete all references to the current {@link android.database.Cursor} |
| 116 | in order to prevent memory leaks. Once |
| 117 | {@link android.support.v4.app.LoaderManager.LoaderCallbacks#onLoaderReset onLoaderReset()} |
| 118 | finishes, {@link android.support.v4.content.CursorLoader} re-runs its query. |
| 119 | </p> |
| 120 | <p> |
| 121 | For example: |
| 122 | </p> |
| 123 | <pre> |
| 124 | /* |
| 125 | * Invoked when the CursorLoader is being reset. For example, this is |
| 126 | * called if the data in the provider changes and the Cursor becomes stale. |
| 127 | */ |
| 128 | @Override |
| 129 | public void onLoaderReset(Loader<Cursor> loader) { |
| 130 | |
| 131 | /* |
| 132 | * Clears out the adapter's reference to the Cursor. |
| 133 | * This prevents memory leaks. |
| 134 | */ |
| 135 | mAdapter.changeCursor(null); |
| 136 | } |
| 137 | </pre> |