1page.title=List View
2page.tags=listview
3@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
30<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
34<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
51href="{@docRoot}tools/support-library/index.html">Support Library</a> so that your app may use them
52while 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/>
153<code>&lt;uses-permission android:name="android.permission.READ_CONTACTS" /></code></p>
154
155