blob: f8315c5777b466ff5d5433c56b1af3ea1076ab9e [file] [log] [blame]
Scott Main50e990c2012-06-21 17:14:39 -07001page.title=List View
Scott Main64461bf2013-04-11 19:32:08 -07002page.tags="listview"
Scott Main50e990c2012-06-21 17:14:39 -07003@jd:body
4<div id="qv-wrapper">
5<div id="qv">
6<h2>In this document</h2>
7 <ol>
8 <li><a href="#Loader">Using a Loader</a></li>
9 <li><a href="#Example">Example</a></li>
10 </ol>
11 <h2>Key classes</h2>
12 <ol>
13 <li>{@link android.widget.ListView}</li>
14 <li>{@link android.widget.Adapter}</li>
15 <li>{@link android.support.v4.content.CursorLoader}</li>
16 </ol>
17 <h2>See also</h2>
18 <ol>
19 <li><a
20href="{@docRoot}guide/components/loaders.html">Loaders</a></li>
21 </ol>
22</div>
23</div>
24
25<p>{@link android.widget.ListView} is a view group that displays a list of
26scrollable items. The list items are automatically inserted to the list using an {@link
27android.widget.Adapter} that pulls content from a source such as an array or database query and
28converts each item result into a view that's placed into the list.</p>
29
Scott Main2d9063b2012-08-08 18:49:28 -070030<p>For an introduction to how you can dynamically insert views using an adapter, read
31<a href="{@docRoot}guide/topics/ui/declaring-layout.html#AdapterViews">Building Layouts with
32 an Adapter</a>.</p>
33
Scott Main50e990c2012-06-21 17:14:39 -070034<img src="{@docRoot}images/ui/listview.png" alt="" />
35
36<h2 id="Loader">Using a Loader</h2>
37
38<p>Using a {@link
39android.support.v4.content.CursorLoader} is the standard way to query a {@link
40android.database.Cursor} as an asynchronous task in order to avoid blocking your app's main thread
41with the query. When the {@link android.support.v4.content.CursorLoader} receives the {@link
42android.database.Cursor} result, the {@link android.support.v4.app.LoaderManager.LoaderCallbacks
43LoaderCallbacks} receives a callback to {@link
44android.support.v4.app.LoaderManager.LoaderCallbacks#onLoadFinished onLoadFinished()}, which is
45where you update your {@link
46android.widget.Adapter} with the new {@link android.database.Cursor} and the list view then
47displays the results.</p>
48
49<p>Although the {@link android.support.v4.content.CursorLoader} APIs were first introduced in
50Android 3.0 (API level 11), they are also available in the <a
Scott Main4e2c9dc2013-07-23 19:35:17 -070051href="{@docRoot}tools/support-library/index.html">Support Library</a> so that your app may use them
Scott Main50e990c2012-06-21 17:14:39 -070052while supporting devices running Android 1.6 or higher.</p>
53
54<p>For more information about using a {@link
55android.support.v4.content.Loader} to asynchronously load data, see the <a
56href="{@docRoot}guide/components/loaders.html">Loaders</a> guide.</p>
57
58
59<h2 id="Example">Example</h2>
60
61<p>The following example uses {@link android.app.ListActivity}, which is an activity that includes
62a {@link android.widget.ListView} as its only layout element by default. It performs a query to
63the <a
64href="{@docRoot}guide/topics/providers/contacts-provider.html">Contacts
65Provider</a> for a list of names and phone numbers.</p>
66
67<p>The activity implements the {@link android.support.v4.app.LoaderManager.LoaderCallbacks
68LoaderCallbacks} interface in order to use a {@link android.support.v4.content.CursorLoader} that
69dynamically loads the data for the list view.</p>
70
71<pre>
72public class ListViewLoader extends ListActivity
73 implements LoaderManager.LoaderCallbacks&lt;Cursor> {
74
75 // This is the Adapter being used to display the list's data
76 SimpleCursorAdapter mAdapter;
77
78 // These are the Contacts rows that we will retrieve
79 static final String[] PROJECTION = new String[] {ContactsContract.Data._ID,
80 ContactsContract.Data.DISPLAY_NAME};
81
82 // This is the select criteria
83 static final String SELECTION = "((" +
84 ContactsContract.Data.DISPLAY_NAME + " NOTNULL) AND (" +
85 ContactsContract.Data.DISPLAY_NAME + " != '' ))";
86
87 &#64;Override
88 protected void onCreate(Bundle savedInstanceState) {
89 super.onCreate(savedInstanceState);
90
91 // Create a progress bar to display while the list loads
92 ProgressBar progressBar = new ProgressBar(this);
93 progressBar.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
94 LayoutParams.WRAP_CONTENT, Gravity.CENTER));
95 progressBar.setIndeterminate(true);
96 getListView().setEmptyView(progressBar);
97
98 // Must add the progress bar to the root of the layout
99 ViewGroup root = (ViewGroup) findViewById(android.R.id.content);
100 root.addView(progressBar);
101
102 // For the cursor adapter, specify which columns go into which views
103 String[] fromColumns = {ContactsContract.Data.DISPLAY_NAME};
104 int[] toViews = {android.R.id.text1}; // The TextView in simple_list_item_1
105
106 // Create an empty adapter we will use to display the loaded data.
107 // We pass null for the cursor, then update it in onLoadFinished()
108 mAdapter = new SimpleCursorAdapter(this,
109 android.R.layout.simple_list_item_1, null,
110 fromColumns, toViews, 0);
111 setListAdapter(mAdapter);
112
113 // Prepare the loader. Either re-connect with an existing one,
114 // or start a new one.
115 getLoaderManager().initLoader(0, null, this);
116 }
117
118 // Called when a new Loader needs to be created
119 public Loader&lt;Cursor> onCreateLoader(int id, Bundle args) {
120 // Now create and return a CursorLoader that will take care of
121 // creating a Cursor for the data being displayed.
122 return new CursorLoader(this, ContactsContract.Data.CONTENT_URI,
123 PROJECTION, SELECTION, null, null);
124 }
125
126 // Called when a previously created loader has finished loading
127 public void onLoadFinished(Loader&lt;Cursor> loader, Cursor data) {
128 // Swap the new cursor in. (The framework will take care of closing the
129 // old cursor once we return.)
130 mAdapter.swapCursor(data);
131 }
132
133 // Called when a previously created loader is reset, making the data unavailable
134 public void onLoaderReset(Loader&lt;Cursor> loader) {
135 // This is called when the last Cursor provided to onLoadFinished()
136 // above is about to be closed. We need to make sure we are no
137 // longer using it.
138 mAdapter.swapCursor(null);
139 }
140
141 &#64;Override
142 public void onListItemClick(ListView l, View v, int position, long id) {
143 // Do something when a list item is clicked
144 }
145}
146</pre>
147
148<p class="note"><strong>Note:</strong> Because this sample performs a query on the <a
149href="{@docRoot}guide/topics/providers/contacts-provider.html">Contacts
150Provider</a>, if you want to
151try this code, your app must request the {@link android.Manifest.permission#READ_CONTACTS}
152permission in the manifest file:<br/>
Scott Main2d9063b2012-08-08 18:49:28 -0700153<code>&lt;uses-permission android:name="android.permission.READ_CONTACTS" /></code></p>
Scott Main50e990c2012-06-21 17:14:39 -0700154