1page.title=Handling the Results
2trainingnavtop=true
3startpage=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>
70public String[] mFromColumns = {
71    DataProviderContract.IMAGE_PICTURENAME_COLUMN
72};
73public int[] mToFields = {
74    R.id.PictureName
75};
76// Gets a handle to a List View
77ListView mListView = (ListView) findViewById(R.id.dataList);
78/*
79 * Defines a SimpleCursorAdapter for the ListView
80 *
81 */
82SimpleCursorAdapter 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
92mListView.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&#64;Override
99public void onLoadFinished(Loader&lt;Cursor&gt; 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&#64;Override
129public void onLoaderReset(Loader&lt;Cursor&gt; 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>
138