• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1page.title=Carregadores
2parent.title=Atividades
3parent.link=activities.html
4@jd:body
5<div id="qv-wrapper">
6<div id="qv">
7    <h2>Neste documento</h2>
8    <ol>
9    <li><a href="#summary">Resumo de API de carregador</a></li>
10    <li><a href="#app">Uso de carregadores em um aplicativo</a>
11      <ol>
12        <li><a href="#requirements"></a></li>
13        <li><a href="#starting">Início de um carregador</a></li>
14        <li><a href="#restarting">Reinício de um carregador</a></li>
15        <li><a href="#callback">Uso dos retornos de chamada de LoaderManager</a></li>
16      </ol>
17    </li>
18    <li><a href="#example">Exemplo</a>
19       <ol>
20         <li><a href="#more_examples">Mais exemplos</a></li>
21        </ol>
22    </li>
23  </ol>
24
25  <h2>Classes principais</h2>
26    <ol>
27      <li>{@link android.app.LoaderManager}</li>
28      <li>{@link android.content.Loader}</li>
29
30    </ol>
31
32    <h2>Exemplos relacionados</h2>
33   <ol>
34     <li> <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LoaderCursor.html">
35LoaderCursor</a></li>
36     <li> <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LoaderThrottle.html">
37LoaderThrottle</a></li>
38   </ol>
39  </div>
40</div>
41
42<p>Introduzidos no Android 3.0, os carregadores facilitam o carregamento assíncrono de dados
43em uma atividade ou fragmento. Os carregadores têm as seguintes características:</p>
44  <ul>
45    <li>Eles estão disponíveis para cada {@link android.app.Activity} e {@link
46android.app.Fragment}.</li>
47    <li>Eles fornecem carregamento assíncrono de dados.</li>
48    <li>Eles monitoram a origem dos dados e fornecem novos resultados
49quando o conteúdo é alterado.</li>
50    <li>Eles reconectam-se automaticamente ao cursor do último carregador
51quando são recriados após uma alteração de configuração. Portanto, eles não precisam reconsultar
52os dados.</li>
53  </ul>
54
55<h2 id="summary">Resumo da API de carregador</h2>
56
57<p>Há várias classes e interfaces que podem ser envolvidas no uso
58de carregadores em um aplicativo. Elas são resumidas nesta tabela:</p>
59
60<table>
61  <tr>
62    <th>Classe/Interface</th>
63    <th>Descrição</th>
64  </tr>
65  <tr>
66    <td>{@link android.app.LoaderManager}</td>
67    <td>Uma classe abstrata associada a {@link android.app.Activity} ou
68{@link android.app.Fragment} para gerenciar uma ou mais instâncias de {@link
69android.content.Loader}. Isto ajuda um aplicativo a gerenciar
70operações executadas por longos períodos juntamente com o ciclo de vida de {@link android.app.Activity}
71ou {@link android.app.Fragment}; o uso mais comum disto é com
72{@link android.content.CursorLoader}. No entanto, os aplicativos têm a liberdade de criar
73os próprios carregadores para outros tipos de dados.
74    <br />
75    <br />
76    Há apenas um {@link android.app.LoaderManager} por atividade ou fragmento. No entanto, um {@link android.app.LoaderManager} pode ter
77vários carregadores.</td>
78  </tr>
79  <tr>
80    <td>{@link android.app.LoaderManager.LoaderCallbacks}</td>
81    <td>Uma interface de retorno de chamada para um cliente interagir com {@link
82android.app.LoaderManager}. Por exemplo, usa-se o método de retorno de chamada {@link
83android.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()}
84para criar um novo carregador.</td>
85  </tr>
86  <tr>
87    <td>{@link android.content.Loader}</td>
88    <td>Uma classe abstrata que realiza carregamento assíncrono de dados. Esta é a classe de base
89de um carregador. Geralmente, você usaria {@link
90android.content.CursorLoader}, mas é possível implementar subclasse própria. Enquanto os carregadores
91estiverem ativos, devem monitorar a origem dos dados e fornecer
92novos resultados quando o conteúdo for alterado. </td>
93  </tr>
94  <tr>
95    <td>{@link android.content.AsyncTaskLoader}</td>
96    <td>Um carregador abstrato que fornece uma {@link android.os.AsyncTask} para realizar o trabalho.</td>
97  </tr>
98  <tr>
99    <td>{@link android.content.CursorLoader}</td>
100    <td>Uma subclasse de {@link android.content.AsyncTaskLoader} que consulta
101{@link android.content.ContentResolver} e retorna um {@link
102android.database.Cursor}. Esta classe implementa o protocolo {@link
103android.content.Loader} de forma padrão para cursores de consulta,
104compilando em {@link android.content.AsyncTaskLoader} para realizar a consulta de cursor
105em um encadeamento de segundo plano para que a IU do aplicativo não seja bloqueada. Usar
106este carregador é a melhor maneira de carregar dados de forma assíncrona a partir de um {@link
107android.content.ContentProvider}, em vez de realizar uma consulta gerenciada pelas
108APIs da atividade ou do fragmento.</td>
109  </tr>
110</table>
111
112<p>As classes e interfaces na tabela acima são os componentes essenciais
113que você usará para implementar um carregador no aplicativo. Você não precisará de todos eles
114para cada carregador criado, mas sempre precisará de uma referência a {@link
115android.app.LoaderManager} para inicializar um carregador e uma implementação
116de uma classe {@link android.content.Loader}, como {@link
117android.content.CursorLoader}. As seguintes seções mostram como usar
118essas classes e interfaces em um aplicativo.</p>
119
120<h2 id ="app">Uso de carregadores em um aplicativo</h2>
121<p>Esta seção descreve como usar os carregadores em um aplicativo do Android. Um aplicativo
122que usa os carregadores, geralmente, inclui o seguinte:</p>
123<ul>
124  <li>Uma {@link android.app.Activity} ou um {@link android.app.Fragment}.</li>
125  <li>Uma instância de {@link android.app.LoaderManager}.</li>
126  <li>Um {@link android.content.CursorLoader} para carregar dados baseados em um {@link
127android.content.ContentProvider}. Alternativamente, é possível implementar a própria subclasse
128de {@link android.content.Loader} ou {@link android.content.AsyncTaskLoader}
129para carregar dados de outra origem.</li>
130  <li>Uma implementação de {@link android.app.LoaderManager.LoaderCallbacks}.
131É aqui que é possível criar novos carregadores e gerenciar as referências
132a carregadores existentes.</li>
133<li>Uma maneira de exibir os dados do carregador, como um {@link
134android.widget.SimpleCursorAdapter}.</li>
135  <li>Uma origem de dados, como um {@link android.content.ContentProvider}, ao usar
136{@link android.content.CursorLoader}.</li>
137</ul>
138<h3 id="starting">Início de um carregador</h3>
139
140<p>O {@link android.app.LoaderManager} gerencia uma ou mais instâncias de {@link
141android.content.Loader} dentro de uma {@link android.app.Activity}
142ou um {@link android.app.Fragment}. Há apenas um {@link
143android.app.LoaderManager} por atividade ou fragmento.</p>
144
145<p>Geralmente,
146inicializa-se um {@link android.content.Loader} dentro do método {@link
147android.app.Activity#onCreate onCreate()} da atividade, ou dentro do método
148{@link android.app.Fragment#onActivityCreated onActivityCreated()} do fragmento. Faça
149isso da seguinte maneira:</p>
150
151<pre>// Prepare the loader.  Either re-connect with an existing one,
152// or start a new one.
153getLoaderManager().initLoader(0, null, this);</pre>
154
155<p>O método {@link android.app.LoaderManager#initLoader initLoader()}
156recebe os seguintes parâmetros:</p>
157<ul>
158  <li>Um ID único que identifica o carregador. Neste exemplo, o ID é 0.</li>
159<li>Argumentos opcionais para fornecer ao carregador
160em construção (<code>null</code> neste exemplo).</li>
161
162<li>Uma implementação de {@link android.app.LoaderManager.LoaderCallbacks},
163que {@link android.app.LoaderManager} chama para relatar eventos do carregador. Nesse exemplo,
164 a classe local implementa a interface de {@link
165android.app.LoaderManager.LoaderCallbacks}, para que ela passe uma referência
166para si, {@code this}.</li>
167</ul>
168<p>A chamada de {@link android.app.LoaderManager#initLoader initLoader()} garante que o carregador
169foi inicializado e que está ativo. Ela possui dois possíveis resultados:</p>
170<ul>
171  <li>Se o carregador especificado pelo ID já existir, o último carregador
172criado será usado novamente.</li>
173  <li>Se o carregador especificado pelo ID <em>não</em> existir,
174{@link android.app.LoaderManager#initLoader initLoader()} ativará o método
175{@link android.app.LoaderManager.LoaderCallbacks} {@link android.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()}.
176É aqui que você implementa o código para instanciar e retornar um novo carregador.
177Para obter mais informações, consulte a seção <a href="#onCreateLoader">onCreateLoader</a>.</li>
178</ul>
179<p>Em qualquer um dos casos, a implementação de {@link android.app.LoaderManager.LoaderCallbacks}
180fornecida é associada ao carregador e será chamada quando o estado
181do carregador mudar.  Se, no momento desta chamada, o autor dela
182estiver no estado inicializado e o carregador solicitado já existir e tiver
183gerado seus dados, o sistema chamará {@link
184android.app.LoaderManager.LoaderCallbacks#onLoadFinished onLoadFinished()}
185imediatamente (durante{@link android.app.LoaderManager#initLoader initLoader()}),
186então prepare-se para tais situações. Consulte <a href="#onLoadFinished">
187onLoadFinished</a> para obter mais informações sobre este retorno de chamada</p>
188
189<p>Observe que o método {@link android.app.LoaderManager#initLoader initLoader()}
190retorna o {@link android.content.Loader} que é criado, mas você não precisará
191capturar uma referência para ele. O {@link android.app.LoaderManager} gerencia
192a vida do carregador automaticamente. O {@link android.app.LoaderManager}
193inicia e interrompe o carregamento quando necessário, além de manter o estado do carregador
194e do conteúdo associado. À medida que isso ocorre, você raramente interage com os carregadores
195diretamente (para ver um exemplo de métodos para aprimorar o comportamento
196de um carregador, consulte o exemplo de <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LoaderThrottle.html"> LoaderThrottle</a>).
197Geralmente, usam-se os métodos {@link
198android.app.LoaderManager.LoaderCallbacks} para intervir no processo de carregamento
199quando determinados eventos ocorrem. Para obter mais informações sobre este assunto, consulte <a href="#callback">Uso dos retornos de chamada de LoaderManager</a>.</p>
200
201<h3 id="restarting">Reinício de um carregador</h3>
202
203<p>Ao usar {@link android.app.LoaderManager#initLoader initLoader()},
204como mostrado acima, ele usará um carregador existente com o ID especificado, se houver um.
205Caso contrário, um carregador será criado. No entanto, às vezes, você quer descartar os dados antigos
206e começar do início.</p>
207
208<p>Para descartar os dados antigos, use {@link
209android.app.LoaderManager#restartLoader restartLoader()}. Por exemplo,
210esta implementação de {@link android.widget.SearchView.OnQueryTextListener} reinicia
211o carregador quando a consulta do usuário é alterada. O carregador precisa ser reiniciado
212para que possa usar o filtro de busca revisado para realizar uma nova consulta:</p>
213
214<pre>
215public boolean onQueryTextChanged(String newText) {
216    // Called when the action bar search text has changed.  Update
217    // the search filter, and restart the loader to do a new query
218    // with this filter.
219    mCurFilter = !TextUtils.isEmpty(newText) ? newText : null;
220    getLoaderManager().restartLoader(0, null, this);
221    return true;
222}</pre>
223
224<h3 id="callback">Uso dos retornos de chamada de LoaderManager</h3>
225
226<p>{@link android.app.LoaderManager.LoaderCallbacks} é uma interface de retorno de chamada
227que permite que um cliente interaja com o {@link android.app.LoaderManager}. </p>
228<p>Carregadores, em determinado {@link android.content.CursorLoader}, devem
229reter os dados após serem interrompidos. Isto permite que os aplicativos
230mantenham os dados dos métodos {@link android.app.Activity#onStop
231onStop()} e {@link android.app.Activity#onStart onStart()} do fragmento ou da atividade
232para que, quando os usuários voltarem a um aplicativo, não tenham que esperar
233o recarregamento dos dados. Você usa os métodos {@link android.app.LoaderManager.LoaderCallbacks}
234para saber quando deve criar um novo carregador, e para dizer ao aplicativo quando
235 deve interromper o uso dos dados de um carregador.</p>
236
237<p>{@link android.app.LoaderManager.LoaderCallbacks} inclui
238esses métodos:</p>
239<ul>
240  <li>{@link android.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()}  —
241instancia e retorna um novo {@link android.content.Loader} para o ID fornecido.
242</li></ul>
243<ul>
244  <li> {@link android.app.LoaderManager.LoaderCallbacks#onLoadFinished onLoadFinished()}
245— chamado quando um carregador anteriormente criado termina o seu carregamento.
246</li></ul>
247<ul>
248  <li>{@link android.app.LoaderManager.LoaderCallbacks#onLoaderReset onLoaderReset()}
249    — chamado quando um carregador anteriormente criado é reiniciado,
250tornando os dados indisponíveis.
251</li>
252</ul>
253<p>Esses métodos são descritos com mais informações nas seguintes seções.</p>
254
255<h4 id ="onCreateLoader">onCreateLoader</h4>
256
257<p>Ao tentar acessar um carregador (por exemplo, por meio de {@link
258android.app.LoaderManager#initLoader initLoader()}), ele verifica
259se o carregador especificado pelo ID existe. Se não existir, ele ativa o método {@link
260android.app.LoaderManager.LoaderCallbacks} {@link
261android.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()}. É aqui
262que você pode criar um novo carregador. Geralmente, será um {@link
263android.content.CursorLoader}, mas é possível implementar a própria subclasse de {@link
264android.content.Loader}. </p>
265
266<p>Nesse exemplo, o método de retorno de chamada de {@link
267android.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()}
268cria um {@link android.content.CursorLoader}. Você deve compilar
269{@link android.content.CursorLoader} usando o método construtor,
270que exige um conjunto completo de informações necessárias para realizar uma consulta ao {@link
271android.content.ContentProvider}. Especificamente, ele precisa de:</p>
272<ul>
273  <li><em>uri</em> — a URI do conteúdo a ser recuperado. </li>
274  <li><em>projection</em> — uma lista de quais colunas devem ser retornadas. Passar
275<code>null</code> retornará todas as colunas, o que é ineficiente. </li>
276  <li><em>selection</em> — um filtro que declara quais linhas devem retornar,
277formatado por uma cláusula SQL WHERE (excluindo WHERE). Passar
278<code>null</code> retornará todas as linhas da URI em questão. </li>
279  <li><em>selectionArgs</em> — é possível incluir interrogações na seleção,
280que serão substituídas pelos valores de <em>selectionArgs</em>, na ordem em que aparecem
281na seleção. Os valores serão vinculados como Strings. </li>
282  <li><em>sortOrder</em> — como ordenar as linhas, formatadas em uma cláusula SQL
283ORDER BY (excluindo ORDER BY). Passar <code>null</code>
284usará a ordem de classificação padrão, que pode ser desordenada.</li>
285</ul>
286<p>Por exemplo:</p>
287<pre>
288 // If non-null, this is the current filter the user has provided.
289String mCurFilter;
290...
291public Loader&lt;Cursor&gt; onCreateLoader(int id, Bundle args) {
292    // This is called when a new Loader needs to be created.  This
293    // sample only has one Loader, so we don't care about the ID.
294    // First, pick the base URI to use depending on whether we are
295    // currently filtering.
296    Uri baseUri;
297    if (mCurFilter != null) {
298        baseUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI,
299                  Uri.encode(mCurFilter));
300    } else {
301        baseUri = Contacts.CONTENT_URI;
302    }
303
304    // Now create and return a CursorLoader that will take care of
305    // creating a Cursor for the data being displayed.
306    String select = &quot;((&quot; + Contacts.DISPLAY_NAME + &quot; NOTNULL) AND (&quot;
307            + Contacts.HAS_PHONE_NUMBER + &quot;=1) AND (&quot;
308            + Contacts.DISPLAY_NAME + &quot; != '' ))&quot;;
309    return new CursorLoader(getActivity(), baseUri,
310            CONTACTS_SUMMARY_PROJECTION, select, null,
311            Contacts.DISPLAY_NAME + &quot; COLLATE LOCALIZED ASC&quot;);
312}</pre>
313<h4 id="onLoadFinished">onLoadFinished</h4>
314
315<p>Este método é chamado quando um carregador anteriormente criado terminar o seu carregamento.
316Este método certamente será chamado antes da liberação dos últimos dados
317que forem fornecidos por este carregador.  Neste ponto, você deve remover todo o uso
318dos dados antigos (já que serão liberados em breve), mas não deve fazer
319a liberação dos dados, já que pertencem ao carregador e ele lidará com isso.</p>
320
321
322<p>O carregador liberará os dados quando souber
323que o aplicativo não está mais usando-os.  Por exemplo, se os dados forem um cursor de um {@link
324android.content.CursorLoader}, você não deve chamar {@link
325android.database.Cursor#close close()} por conta própria. Se o cursor estiver
326sendo colocado em um {@link android.widget.CursorAdapter}, você deve usar o método {@link
327android.widget.SimpleCursorAdapter#swapCursor swapCursor()}  para que o antigo
328{@link android.database.Cursor} não seja fechado. Por exemplo:</p>
329
330<pre>
331// This is the Adapter being used to display the list's data.<br
332/>SimpleCursorAdapter mAdapter;
333...
334
335public void onLoadFinished(Loader&lt;Cursor&gt; loader, Cursor data) {
336    // Swap the new cursor in.  (The framework will take care of closing the
337    // old cursor once we return.)
338    mAdapter.swapCursor(data);
339}</pre>
340
341<h4 id="onLoaderReset">onLoaderReset</h4>
342
343<p>Este método é chamado quando um carregador anteriormente criado é reiniciado,
344tornando os dados indisponíveis. Este retorno de chamada permite que você descubra quando os dados
345estão prestes a serem liberados para que seja possível remover a referência a eles.  </p>
346<p>Esta implementação chama
347{@link android.widget.SimpleCursorAdapter#swapCursor swapCursor()}
348com um valor de <code>null</code>:</p>
349
350<pre>
351// This is the Adapter being used to display the list's data.
352SimpleCursorAdapter mAdapter;
353...
354
355public void onLoaderReset(Loader&lt;Cursor&gt; loader) {
356    // This is called when the last Cursor provided to onLoadFinished()
357    // above is about to be closed.  We need to make sure we are no
358    // longer using it.
359    mAdapter.swapCursor(null);
360}</pre>
361
362
363<h2 id="example">Exemplo</h2>
364
365<p>Como exemplo, a seguir há uma implementação completa de um {@link
366android.app.Fragment} que exibe uma {@link android.widget.ListView} contendo
367os resultados de uma consulta aos provedores de conteúdo de contatos. Ela usa um {@link
368android.content.CursorLoader} para gerenciar a consulta no provedor.</p>
369
370<p>Para um aplicativo acessar os contatos de um usuário, como neste exemplo,
371o manifesto deverá incluir a permissão
372{@link android.Manifest.permission#READ_CONTACTS READ_CONTACTS}.</p>
373
374<pre>
375public static class CursorLoaderListFragment extends ListFragment
376        implements OnQueryTextListener, LoaderManager.LoaderCallbacks&lt;Cursor&gt; {
377
378    // This is the Adapter being used to display the list's data.
379    SimpleCursorAdapter mAdapter;
380
381    // If non-null, this is the current filter the user has provided.
382    String mCurFilter;
383
384    @Override public void onActivityCreated(Bundle savedInstanceState) {
385        super.onActivityCreated(savedInstanceState);
386
387        // Give some text to display if there is no data.  In a real
388        // application this would come from a resource.
389        setEmptyText(&quot;No phone numbers&quot;);
390
391        // We have a menu item to show in action bar.
392        setHasOptionsMenu(true);
393
394        // Create an empty adapter we will use to display the loaded data.
395        mAdapter = new SimpleCursorAdapter(getActivity(),
396                android.R.layout.simple_list_item_2, null,
397                new String[] { Contacts.DISPLAY_NAME, Contacts.CONTACT_STATUS },
398                new int[] { android.R.id.text1, android.R.id.text2 }, 0);
399        setListAdapter(mAdapter);
400
401        // Prepare the loader.  Either re-connect with an existing one,
402        // or start a new one.
403        getLoaderManager().initLoader(0, null, this);
404    }
405
406    @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
407        // Place an action bar item for searching.
408        MenuItem item = menu.add(&quot;Search&quot;);
409        item.setIcon(android.R.drawable.ic_menu_search);
410        item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
411        SearchView sv = new SearchView(getActivity());
412        sv.setOnQueryTextListener(this);
413        item.setActionView(sv);
414    }
415
416    public boolean onQueryTextChange(String newText) {
417        // Called when the action bar search text has changed.  Update
418        // the search filter, and restart the loader to do a new query
419        // with this filter.
420        mCurFilter = !TextUtils.isEmpty(newText) ? newText : null;
421        getLoaderManager().restartLoader(0, null, this);
422        return true;
423    }
424
425    @Override public boolean onQueryTextSubmit(String query) {
426        // Don't care about this.
427        return true;
428    }
429
430    @Override public void onListItemClick(ListView l, View v, int position, long id) {
431        // Insert desired behavior here.
432        Log.i(&quot;FragmentComplexList&quot;, &quot;Item clicked: &quot; + id);
433    }
434
435    // These are the Contacts rows that we will retrieve.
436    static final String[] CONTACTS_SUMMARY_PROJECTION = new String[] {
437        Contacts._ID,
438        Contacts.DISPLAY_NAME,
439        Contacts.CONTACT_STATUS,
440        Contacts.CONTACT_PRESENCE,
441        Contacts.PHOTO_ID,
442        Contacts.LOOKUP_KEY,
443    };
444    public Loader&lt;Cursor&gt; onCreateLoader(int id, Bundle args) {
445        // This is called when a new Loader needs to be created.  This
446        // sample only has one Loader, so we don't care about the ID.
447        // First, pick the base URI to use depending on whether we are
448        // currently filtering.
449        Uri baseUri;
450        if (mCurFilter != null) {
451            baseUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI,
452                    Uri.encode(mCurFilter));
453        } else {
454            baseUri = Contacts.CONTENT_URI;
455        }
456
457        // Now create and return a CursorLoader that will take care of
458        // creating a Cursor for the data being displayed.
459        String select = &quot;((&quot; + Contacts.DISPLAY_NAME + &quot; NOTNULL) AND (&quot;
460                + Contacts.HAS_PHONE_NUMBER + &quot;=1) AND (&quot;
461                + Contacts.DISPLAY_NAME + &quot; != '' ))&quot;;
462        return new CursorLoader(getActivity(), baseUri,
463                CONTACTS_SUMMARY_PROJECTION, select, null,
464                Contacts.DISPLAY_NAME + &quot; COLLATE LOCALIZED ASC&quot;);
465    }
466
467    public void onLoadFinished(Loader&lt;Cursor&gt; loader, Cursor data) {
468        // Swap the new cursor in.  (The framework will take care of closing the
469        // old cursor once we return.)
470        mAdapter.swapCursor(data);
471    }
472
473    public void onLoaderReset(Loader&lt;Cursor&gt; loader) {
474        // This is called when the last Cursor provided to onLoadFinished()
475        // above is about to be closed.  We need to make sure we are no
476        // longer using it.
477        mAdapter.swapCursor(null);
478    }
479}</pre>
480<h3 id="more_examples">Mais exemplos</h3>
481
482<p>Há alguns exemplos variados na <strong>ApiDemos</strong>
483que ilustra o uso de carregadores:</p>
484<ul>
485  <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LoaderCursor.html">
486LoaderCursor</a> — uma versão completa do
487fragmento exibido acima.</li>
488  <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LoaderThrottle.html"> LoaderThrottle</a> — um exemplo de como usar o regulador
489para reduzir o número de consultas que o provedor de conteúdo realiza quando os dados são alterados.</li>
490</ul>
491
492<p>Para obter mais informações sobre o download e a instalação de exemplos de SDK, consulte <a href="http://developer.android.com/resources/samples/get.html">Obtenção
493dos exemplos</a>. </p>
494
495