Home | History | Annotate | Download | only in contacts-provider
      1 page.title=Displaying the Quick Contact Badge
      2 
      3 trainingnavtop=true
      4 @jd:body
      5 
      6 
      7 <div id="tb-wrapper">
      8 <div id="tb">
      9 
     10 <!-- table of contents -->
     11 <h2>This lesson teaches you to</h2>
     12 <ol>
     13     <li>
     14         <a href="#AddView">Add a QuickContactBadge View</a>
     15     </li>
     16     <li>
     17         <a href="#SetURIThumbnail">Set the Contact URI and Thumbnail</a>
     18     </li>
     19     <li>
     20         <a href="#ListView">
     21             Add a QuickContactBadge to a ListView
     22         </a>
     23     </li>
     24 </ol>
     25 
     26 <!-- other docs (NOT javadocs) -->
     27 <h2>You should also read</h2>
     28 <ul>
     29     <li>
     30         <a href="{@docRoot}guide/topics/providers/content-provider-basics.html">
     31         Content Provider Basics
     32         </a>
     33     </li>
     34     <li>
     35         <a href="{@docRoot}guide/topics/providers/contacts-provider.html">
     36         Contacts Provider
     37         </a>
     38     </li>
     39 </ul>
     40 
     41 <h2>Try it out</h2>
     42 
     43 <div class="download-box">
     44     <a href="http://developer.android.com/shareables/training/ContactsList.zip" class="button">
     45     Download the sample
     46     </a>
     47  <p class="filename">ContactsList.zip</p>
     48 </div>
     49 
     50 </div>
     51 </div>
     52 <p>
     53     This lesson shows you how to add a {@link android.widget.QuickContactBadge} to your UI
     54     and how to bind data to it. A {@link android.widget.QuickContactBadge} is a widget that
     55     initially appears as a thumbnail image. Although you can use any {@link android.graphics.Bitmap}
     56     for the thumbnail image, you usually use a {@link android.graphics.Bitmap} decoded from the
     57     contact's photo thumbnail image.
     58 </p>
     59 <p>
     60     The small image acts as a control; when users click on the image, the
     61     {@link android.widget.QuickContactBadge} expands into a dialog containing the following:
     62 </p>
     63 <dl>
     64     <dt>A large image</dt>
     65     <dd>
     66         The large image associated with the contact, or no image is available, a placeholder
     67         graphic.
     68     </dd>
     69     <dt>
     70         App icons
     71     </dt>
     72     <dd>
     73         An app icon for each piece of detail data that can be handled by a built-in app. For
     74         example, if the contact's details include one or more email addresses, an email icon
     75         appears. When users click the icon, all of the contact's email addresses appear. When users
     76         click one of the addresses, the email app displays a screen for composing a message to the
     77         selected email address.
     78     </dd>
     79 </dl>
     80 <p>
     81     The {@link android.widget.QuickContactBadge} view provides instant access to a contact's
     82     details, as well as a fast way of communicating with the contact. Users don't have to look up
     83     a contact, find and copy information, and then paste it into the appropriate app. Instead, they
     84     can click on the {@link android.widget.QuickContactBadge}, choose the communication method they
     85     want to use, and send the information for that method directly to the appropriate app.
     86 </p>
     87 <h2 id="AddView">Add a QuickContactBadge View</h2>
     88 <p>
     89     To add a {@link android.widget.QuickContactBadge}, insert a
     90     <code>&lt;QuickContactBadge&gt;</code> element in your layout. For example:
     91 </p>
     92 <pre>
     93 &lt;RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
     94                 android:layout_width="match_parent"
     95                 android:layout_height="match_parent"&gt;
     96 ...
     97     &lt;QuickContactBadge
     98                android:id=&#64;+id/quickbadge
     99                android:layout_height="wrap_content"
    100                android:layout_width="wrap_content"
    101                android:scaleType="centerCrop"/&gt;
    102     ...
    103 &lt;/RelativeLayout&gt;
    104 </pre>
    105 <h2 id="">Retrieve provider data</h2>
    106 <p>
    107     To display a contact in the {@link android.widget.QuickContactBadge}, you need a content URI
    108     for the contact and a {@link android.graphics.Bitmap} for the small image. You generate
    109     both the content URI and the {@link android.graphics.Bitmap} from columns retrieved from the
    110     Contacts Provider. Specify these columns as part of the projection you use to load data into
    111     your {@link android.database.Cursor}.
    112 </p>
    113 <p>
    114     For Android 3.0 (API level 11) and later, include the following columns in your projection:</p>
    115 <ul>
    116     <li>{@link android.provider.ContactsContract.Contacts#_ID Contacts._ID}</li>
    117     <li>{@link android.provider.ContactsContract.Contacts#LOOKUP_KEY Contacts.LOOKUP_KEY}</li>
    118     <li>
    119         {@link android.provider.ContactsContract.Contacts#PHOTO_THUMBNAIL_URI
    120         Contacts.PHOTO_THUMBNAIL_URI}
    121     </li>
    122 </ul>
    123 <p>
    124     For Android 2.3.3 (API level 10) and earlier, use the following columns:
    125 </p>
    126 <ul>
    127     <li>{@link android.provider.ContactsContract.Contacts#_ID Contacts._ID}</li>
    128     <li>{@link android.provider.ContactsContract.Contacts#LOOKUP_KEY Contacts.LOOKUP_KEY}</li>
    129 </ul>
    130 <p>
    131     The remainder of this lesson assumes that you've already loaded a
    132     {@link android.database.Cursor} that contains these columns as well as others you may have
    133     chosen. To learn how to retrieve this columns in a {@link android.database.Cursor}, read the
    134     lesson <a href="retrieve-names.html">Retrieving a List of Contacts</a>.
    135 </p>
    136 <h2 id="SetURIThumbnail">Set the Contact URI and Thumbnail</h2>
    137 <p>
    138     Once you have the necessary columns, you can bind data to the
    139     {@link android.widget.QuickContactBadge}.
    140 </p>
    141 <h3>Set the Contact URI</h3>
    142 <p>
    143     To set the content URI for the contact, call
    144     {@link android.provider.ContactsContract.Contacts#getLookupUri getLookupUri(id,lookupKey)} to
    145     get a {@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI}, then
    146     call {@link android.widget.QuickContactBadge#assignContactUri assignContactUri()} to set the
    147     contact. For example:
    148 </p>
    149 <pre>
    150     // The Cursor that contains contact rows
    151     Cursor mCursor;
    152     // The index of the _ID column in the Cursor
    153     int mIdColumn;
    154     // The index of the LOOKUP_KEY column in the Cursor
    155     int mLookupKeyColumn;
    156     // A content URI for the desired contact
    157     Uri mContactUri;
    158     // A handle to the QuickContactBadge view
    159     QuickContactBadge mBadge;
    160     ...
    161     mBadge = (QuickContactBadge) findViewById(R.id.quickbadge);
    162     /*
    163      * Insert code here to move to the desired cursor row
    164      */
    165     // Gets the _ID column index
    166     mIdColumn = mCursor.getColumnIndex(Contacts._ID);
    167     // Gets the LOOKUP_KEY index
    168     mLookupKeyColumn = mCursor.getColumnIndex(Contacts.LOOKUP_KEY);
    169     // Gets a content URI for the contact
    170     mContactUri =
    171             Contacts.getLookupUri(
    172                 mCursor.getLong(mIdColumn),
    173                 mCursor.getString(mLookupKeyColumn)
    174             );
    175     mBadge.assignContactUri(mContactUri);
    176 </pre>
    177 <p>
    178     When users click the {@link android.widget.QuickContactBadge} icon, the contact's
    179     details automatically appear in the dialog.
    180 </p>
    181 <h3>Set the photo thumbnail</h3>
    182 <p>
    183     Setting the contact URI for the {@link android.widget.QuickContactBadge} does not automatically
    184     load the contact's thumbnail photo. To load the photo, get a URI for the photo from the
    185     contact's {@link android.database.Cursor} row, use it to open the file containing the compressed
    186     thumbnail photo, and read the file into a {@link android.graphics.Bitmap}.
    187 </p>
    188 <p class="note">
    189     <strong>Note:</strong> The
    190     {@link android.provider.ContactsContract.Contacts#PHOTO_THUMBNAIL_URI} column isn't available
    191     in platform versions prior to 3.0. For those versions, you must retrieve the URI
    192     from the {@link android.provider.ContactsContract.Contacts.Photo Contacts.Photo} subtable.
    193 </p>
    194 <p>
    195     First, set up variables for accessing the {@link android.database.Cursor} containing the
    196     {@link android.provider.ContactsContract.Contacts#_ID Contacts._ID} and
    197     {@link android.provider.ContactsContract.Contacts#LOOKUP_KEY Contacts.LOOKUP_KEY} columns, as
    198     described previously:
    199 </p>
    200 <pre>
    201     // The column in which to find the thumbnail ID
    202     int mThumbnailColumn;
    203     /*
    204      * The thumbnail URI, expressed as a String.
    205      * Contacts Provider stores URIs as String values.
    206      */
    207     String mThumbnailUri;
    208     ...
    209     /*
    210      * Gets the photo thumbnail column index if
    211      * platform version &gt;= Honeycomb
    212      */
    213     if (Build.VERSION.SDK_INT &gt;= Build.VERSION_CODES.HONEYCOMB) {
    214         mThumbnailColumn =
    215                 mCursor.getColumnIndex(Contacts.PHOTO_THUMBNAIL_URI);
    216     // Otherwise, sets the thumbnail column to the _ID column
    217     } else {
    218         mThumbnailColumn = mIdColumn;
    219     }
    220     /*
    221      * Assuming the current Cursor position is the contact you want,
    222      * gets the thumbnail ID
    223      */
    224     mThumbnailUri = mCursor.getString(mThumbnailColumn);
    225     ...
    226 </pre>
    227 <p>
    228     Define a method that takes photo-related data for the contact and dimensions for the
    229     destination view,  and returns the properly-sized thumbnail in a
    230     {@link android.graphics.Bitmap}. Start by constructing a URI that points to the
    231     thumbnail:
    232 <p>
    233 <pre>
    234     /**
    235      * Load a contact photo thumbnail and return it as a Bitmap,
    236      * resizing the image to the provided image dimensions as needed.
    237      * @param photoData photo ID Prior to Honeycomb, the contact's _ID value.
    238      * For Honeycomb and later, the value of PHOTO_THUMBNAIL_URI.
    239      * @return A thumbnail Bitmap, sized to the provided width and height.
    240      * Returns null if the thumbnail is not found.
    241      */
    242     private Bitmap loadContactPhotoThumbnail(String photoData) {
    243         // Creates an asset file descriptor for the thumbnail file.
    244         AssetFileDescriptor afd = null;
    245         // try-catch block for file not found
    246         try {
    247             // Creates a holder for the URI.
    248             Uri thumbUri;
    249             // If Android 3.0 or later
    250             if (Build.VERSION.SDK_INT
    251                     &gt;=
    252                 Build.VERSION_CODES.HONEYCOMB) {
    253                 // Sets the URI from the incoming PHOTO_THUMBNAIL_URI
    254                 thumbUri = Uri.parse(photoData);
    255             } else {
    256             // Prior to Android 3.0, constructs a photo Uri using _ID
    257                 /*
    258                  * Creates a contact URI from the Contacts content URI
    259                  * incoming photoData (_ID)
    260                  */
    261                 final Uri contactUri = Uri.withAppendedPath(
    262                         Contacts.CONTENT_URI, photoData);
    263                 /*
    264                  * Creates a photo URI by appending the content URI of
    265                  * Contacts.Photo.
    266                  */
    267                 thumbUri =
    268                         Uri.withAppendedPath(
    269                                 contactUri, Photo.CONTENT_DIRECTORY);
    270             }
    271     
    272         /*
    273          * Retrieves an AssetFileDescriptor object for the thumbnail
    274          * URI
    275          * using ContentResolver.openAssetFileDescriptor
    276          */
    277         afd = getActivity().getContentResolver().
    278                 openAssetFileDescriptor(thumbUri, "r");
    279         /*
    280          * Gets a file descriptor from the asset file descriptor.
    281          * This object can be used across processes.
    282          */
    283         FileDescriptor fileDescriptor = afd.getFileDescriptor();
    284         // Decode the photo file and return the result as a Bitmap
    285         // If the file descriptor is valid
    286         if (fileDescriptor != null) {
    287             // Decodes the bitmap
    288             return BitmapFactory.decodeFileDescriptor(
    289                     fileDescriptor, null, null);
    290             }
    291         // If the file isn't found
    292         } catch (FileNotFoundException e) {
    293             /*
    294              * Handle file not found errors
    295              */
    296         }
    297         // In all cases, close the asset file descriptor
    298         } finally {
    299             if (afd != null) {
    300                 try {
    301                     afd.close();
    302                 } catch (IOException e) {}
    303             }
    304         }
    305         return null;
    306     }
    307 </pre>
    308 <p>
    309     Call the <code>loadContactPhotoThumbnail()</code> method in your code to get the
    310     thumbnail {@link android.graphics.Bitmap}, and use the result to set the photo thumbnail in
    311     your {@link android.widget.QuickContactBadge}:
    312 </p>
    313 <pre>
    314     ...
    315     /*
    316      * Decodes the thumbnail file to a Bitmap.
    317      */
    318     Bitmap mThumbnail =
    319             loadContactPhotoThumbnail(mThumbnailUri);
    320     /*
    321      * Sets the image in the QuickContactBadge
    322      * QuickContactBadge inherits from ImageView, so
    323      */
    324     mBadge.setImageBitmap(mThumbnail);
    325 </pre>
    326 <h2 id="ListView">Add a QuickContactBadge to a ListView</h2>
    327 <p>
    328     A {@link android.widget.QuickContactBadge} is a useful addition to a
    329     {@link android.widget.ListView} that displays a list of contacts. Use the
    330     {@link android.widget.QuickContactBadge} to display a thumbnail photo for each contact; when
    331     users click the thumbnail, the {@link android.widget.QuickContactBadge} dialog appears.
    332 </p>
    333 <h3>Add the QuickContactBadge element</h3>
    334 <p>
    335     To start, add a {@link android.widget.QuickContactBadge} view element to your item layout
    336     For example, if you want to display a {@link android.widget.QuickContactBadge} and a name for
    337     each contact you retrieve, put the following XML into a layout file:
    338 </p>
    339 <pre>
    340 &lt;RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    341                 android:layout_width="match_parent"
    342                 android:layout_height="wrap_content"&gt;
    343     &lt;QuickContactBadge
    344         android:id="&#64;+id/quickcontact"
    345         android:layout_height="wrap_content"
    346         android:layout_width="wrap_content"
    347         android:scaleType="centerCrop"/&gt;
    348     &lt;TextView android:id="&#64;+id/displayname"
    349               android:layout_width="match_parent"
    350               android:layout_height="wrap_content"
    351               android:layout_toRightOf="&#64;+id/quickcontact"
    352               android:gravity="center_vertical"
    353               android:layout_alignParentRight="true"
    354               android:layout_alignParentTop="true"/&gt;
    355 &lt;/RelativeLayout&gt;
    356 </pre>
    357 <p>
    358     In the following sections, this file is referred to as <code>contact_item_layout.xml</code>.
    359 </p>
    360 <h3>Set up a custom CursorAdapter</h3>
    361 <p>
    362     To bind a {@link android.support.v4.widget.CursorAdapter} to a {@link android.widget.ListView}
    363     containing a {@link android.widget.QuickContactBadge}, define a custom adapter that
    364     extends {@link android.support.v4.widget.CursorAdapter}. This approach allows you to process the
    365     data in the {@link android.database.Cursor} before you bind it to the
    366     {@link android.widget.QuickContactBadge}. This approach also allows you to bind multiple
    367     {@link android.database.Cursor} columns to the {@link android.widget.QuickContactBadge}. Neither
    368     of these operations is possible in a regular {@link android.support.v4.widget.CursorAdapter}.
    369 </p>
    370 <p>
    371     The subclass of {@link android.support.v4.widget.CursorAdapter} that you define must
    372     override the following methods:
    373 </p>
    374 <dl>
    375     <dt>{@link android.support.v4.widget.CursorAdapter#newView CursorAdapter.newView()}</dt>
    376     <dd>
    377         Inflates a new {@link android.view.View} object to hold the item layout. In the override
    378         of this method, store handles to the child {@link android.view.View} objects of the layout,
    379         including the child {@link android.widget.QuickContactBadge}. By taking this approach, you
    380         avoid having to get handles to the child {@link android.view.View} objects each time you
    381         inflate a new layout.
    382         <p>
    383             You must override this method so you can get handles to the individual child
    384             {@link android.view.View} objects. This technique allows you to control their binding in
    385             {@link android.support.v4.widget.CursorAdapter#bindView CursorAdapter.bindView()}.
    386         </p>
    387     </dd>
    388     <dt>{@link android.support.v4.widget.CursorAdapter#bindView CursorAdapter.bindView()}</dt>
    389     <dd>
    390         Moves data from the current {@link android.database.Cursor} row to the child
    391         {@link android.view.View} objects of the item layout. You must override this method so
    392         you can bind both the contact's URI and thumbnail to the
    393         {@link android.widget.QuickContactBadge}. The default implementation only allows a 1-to-1
    394         mapping between a column and a {@link android.view.View}
    395     </dd>
    396 </dl>
    397 <p>
    398     The following code snippet contains an example of a custom subclass of
    399     {@link android.support.v4.widget.CursorAdapter}:
    400 </p>
    401 <h3>Define the custom list adapter</h3>
    402 <p>
    403     Define the subclass of {@link android.support.v4.widget.CursorAdapter} including its
    404     constructor, and override
    405     {@link android.support.v4.widget.CursorAdapter#newView newView()} and
    406     {@link android.support.v4.widget.CursorAdapter#bindView bindView()}:
    407 </p>
    408 <pre>
    409     /**
    410      *
    411      *
    412      */
    413     private class ContactsAdapter extends CursorAdapter {
    414         private LayoutInflater mInflater;
    415         ...
    416         public ContactsAdapter(Context context) {
    417             super(context, null, 0);
    418 
    419             /*
    420              * Gets an inflater that can instantiate
    421              * the ListView layout from the file.
    422              */
    423             mInflater = LayoutInflater.from(context);
    424             ...
    425         }
    426         ...
    427         /**
    428          * Defines a class that hold resource IDs of each item layout
    429          * row to prevent having to look them up each time data is
    430          * bound to a row.
    431          */
    432         private class ViewHolder {
    433             TextView displayname;
    434             QuickContactBadge quickcontact;
    435         }
    436         ..
    437         &#64;Override
    438         public View newView(
    439                 Context context,
    440                 Cursor cursor,
    441                 ViewGroup viewGroup) {
    442             /* Inflates the item layout. Stores resource IDs in a
    443              * in a ViewHolder class to prevent having to look
    444              * them up each time bindView() is called.
    445              */
    446             final View itemView =
    447                     mInflater.inflate(
    448                             R.layout.contact_list_layout,
    449                             viewGroup,
    450                             false
    451                     );
    452             final ViewHolder holder = new ViewHolder();
    453             holder.displayname =
    454                     (TextView) view.findViewById(R.id.displayname);
    455             holder.quickcontact =
    456                     (QuickContactBadge)
    457                             view.findViewById(R.id.quickcontact);
    458             view.setTag(holder);
    459             return view;
    460         }
    461         ...
    462         &#64;Override
    463         public void bindView(
    464                 View view,
    465                 Context context,
    466                 Cursor cursor) {
    467             final ViewHolder holder = (ViewHolder) view.getTag();
    468             final String photoData =
    469                     cursor.getString(mPhotoDataIndex);
    470             final String displayName =
    471                     cursor.getString(mDisplayNameIndex);
    472             ...
    473             // Sets the display name in the layout
    474             holder.displayname = cursor.getString(mDisplayNameIndex);
    475             ...
    476             /*
    477              * Generates a contact URI for the QuickContactBadge.
    478              */
    479             final Uri contactUri = Contacts.getLookupUri(
    480                     cursor.getLong(mIdIndex),
    481                     cursor.getString(mLookupKeyIndex));
    482             holder.quickcontact.assignContactUri(contactUri);
    483             String photoData = cursor.getString(mPhotoDataIndex);
    484             /*
    485              * Decodes the thumbnail file to a Bitmap.
    486              * The method loadContactPhotoThumbnail() is defined
    487              * in the section "Set the Contact URI and Thumbnail"
    488              */
    489             Bitmap thumbnailBitmap =
    490                     loadContactPhotoThumbnail(photoData);
    491             /*
    492              * Sets the image in the QuickContactBadge
    493              * QuickContactBadge inherits from ImageView
    494              */
    495             holder.quickcontact.setImageBitmap(thumbnailBitmap);
    496     }
    497 </pre>
    498 
    499 <h3>Set up variables</h3>
    500 <p>
    501     In your code, set up variables, including a {@link android.database.Cursor} projection that
    502     includes the necessary columns.
    503 </p>
    504 <p class="note">
    505     <strong>Note:</strong> The following code snippets use the method
    506     <code>loadContactPhotoThumbnail()</code>, which is defined in the section
    507     <a href="#SetURIThumbnail">Set the Contact URI and Thumbnail</a>
    508 </p>
    509 <p>
    510     For example:
    511 </p>
    512 <pre>
    513 public class ContactsFragment extends Fragment implements
    514         LoaderManager.LoaderCallbacks&lt;Cursor&gt; {
    515 ...
    516     // Defines a ListView
    517     private ListView mListView;
    518     // Defines a ContactsAdapter
    519     private ContactsAdapter mAdapter;
    520     ...
    521     // Defines a Cursor to contain the retrieved data
    522     private Cursor mCursor;
    523     /*
    524      * Defines a projection based on platform version. This ensures
    525      * that you retrieve the correct columns.
    526      */
    527     private static final String[] PROJECTION =
    528             {
    529                 Contacts._ID,
    530                 Contacts.LOOKUP_KEY,
    531                 (Build.VERSION.SDK_INT &gt;=
    532                  Build.VERSION_CODES.HONEYCOMB) ?
    533                         Contacts.DISPLAY_NAME_PRIMARY :
    534                         Contacts.DISPLAY_NAME
    535                 (Build.VERSION.SDK_INT &gt;=
    536                  Build.VERSION_CODES.HONEYCOMB) ?
    537                         Contacts.PHOTO_THUMBNAIL_ID :
    538                         /*
    539                          * Although it's not necessary to include the
    540                          * column twice, this keeps the number of
    541                          * columns the same regardless of version
    542                          */
    543                         Contacts_ID
    544                 ...
    545             };
    546     /*
    547      * As a shortcut, defines constants for the
    548      * column indexes in the Cursor. The index is
    549      * 0-based and always matches the column order
    550      * in the projection.
    551      */
    552     // Column index of the _ID column
    553     private int mIdIndex = 0;
    554     // Column index of the LOOKUP_KEY column
    555     private int mLookupKeyIndex = 1;
    556     // Column index of the display name column
    557     private int mDisplayNameIndex = 3;
    558     /*
    559      * Column index of the photo data column.
    560      * It's PHOTO_THUMBNAIL_URI for Honeycomb and later,
    561      * and _ID for previous versions.
    562      */
    563     private int mPhotoDataIndex =
    564             Build.VERSION.SDK_INT &gt;= Build.VERSION_CODES.HONEYCOMB ?
    565             3 :
    566             0;
    567     ...
    568 </pre>
    569 <h3>Set up the ListView</h3>
    570 <p>
    571     In {@link android.support.v4.app.Fragment#onCreate Fragment.onCreate()}, instantiate the custom
    572     cursor adapter and get a handle to the {@link android.widget.ListView}:
    573 </p>
    574 <pre>
    575     &#64;Override
    576     public void onCreate(Bundle savedInstanceState) {
    577         ...
    578         /*
    579          * Instantiates the subclass of
    580          * CursorAdapter
    581          */
    582         ContactsAdapter mContactsAdapter =
    583                 new ContactsAdapter(getActivity());
    584         /*
    585          * Gets a handle to the ListView in the file
    586          * contact_list_layout.xml
    587          */
    588         mListView = (ListView) findViewById(R.layout.contact_list_layout);
    589         ...
    590     }
    591     ...
    592 </pre>
    593 <p>
    594     In {@link android.support.v4.app.Fragment#onActivityCreated onActivityCreated()}, bind the
    595     <code>ContactsAdapter</code> to the {@link android.widget.ListView}:
    596 </p>
    597 <pre>
    598     &#64;Override
    599     public void onActivityCreated(Bundle savedInstanceState) {
    600         ...
    601         // Sets up the adapter for the ListView
    602         mListView.setAdapter(mAdapter);
    603         ...
    604     }
    605     ...
    606 </pre>
    607 <p>
    608     When you get back a {@link android.database.Cursor} containing the contacts data, usually in
    609     {@link android.support.v4.app.LoaderManager.LoaderCallbacks#onLoadFinished onLoadFinished()},
    610     call {@link android.support.v4.widget.CursorAdapter#swapCursor swapCursor()} to move the
    611     {@link android.database.Cursor} data to the {@link android.widget.ListView}. This displays the
    612     {@link android.widget.QuickContactBadge} for each entry in the list of contacts:
    613 </p>
    614 <pre>
    615     public void onLoadFinished(Loader&lt;Cursor&gt; loader, Cursor cursor) {
    616         // When the loader has completed, swap the cursor into the adapter.
    617         mContactsAdapter.swapCursor(cursor);
    618     }
    619 </pre>
    620 <p>
    621     When you bind a {@link android.database.Cursor} to a
    622     {@link android.widget.ListView} with a {@link android.support.v4.widget.CursorAdapter}
    623     (or subclass), and you use a {@link android.support.v4.content.CursorLoader} to load the
    624     {@link android.database.Cursor}, always clear references to the {@link android.database.Cursor}
    625     in your implementation of
    626     {@link android.support.v4.app.LoaderManager.LoaderCallbacks#onLoaderReset onLoaderReset()}.
    627     For example:
    628 </p>
    629 <pre>
    630     &#64;Override
    631     public void onLoaderReset(Loader&lt;Cursor&gt; loader) {
    632         // Removes remaining reference to the previous Cursor
    633         mContactsAdapter.swapCursor(null);
    634     }
    635 </pre>
    636