summaryrefslogtreecommitdiffstats
path: root/docs/html/training/load-data-background/handle-results.jd
blob: ce0024f031c2674c791758169a3517dbd4e09329 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
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
 */
&#64;Override
public void onLoadFinished(Loader&lt;Cursor&gt; 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.
 */
&#64;Override
public void onLoaderReset(Loader&lt;Cursor&gt; loader) {
    
    /*
     * Clears out the adapter's reference to the Cursor.
     * This prevents memory leaks.
     */
    mAdapter.changeCursor(null);
}
</pre>