• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1page.title=Trình tải
2parent.title=Hoạt động
3parent.link=activities.html
4@jd:body
5<div id="qv-wrapper">
6<div id="qv">
7    <h2>Trong tài liệu này</h2>
8    <ol>
9    <li><a href="#summary">Tổng quan về API Trình tải</a></li>
10    <li><a href="#app">Sử dụng các Trình tải trong một Ứng dụng</a>
11      <ol>
12        <li><a href="#requirements"></a></li>
13        <li><a href="#starting">Khởi động một Trình tải</a></li>
14        <li><a href="#restarting">Khởi động lại một Trình tải</a></li>
15        <li><a href="#callback">Sử dụng các Phương pháp Gọi lại LoaderManager</a></li>
16      </ol>
17    </li>
18    <li><a href="#example">Ví dụ</a>
19       <ol>
20         <li><a href="#more_examples">Thêm Ví dụ</a></li>
21        </ol>
22    </li>
23  </ol>
24
25  <h2>Lớp khóa</h2>
26    <ol>
27      <li>{@link android.app.LoaderManager}</li>
28      <li>{@link android.content.Loader}</li>
29
30    </ol>
31
32    <h2>Các mẫu liên quan</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>Được giới thiệu trong Android 3.0, trình tải giúp việc tải dữ liệu không đồng bộ
43trong một hoạt động hoặc phân đoạn trở nên dễ dàng. Trình tải có những đặc điểm sau:</p>
44  <ul>
45    <li>Chúng sẵn có cho mọi {@link android.app.Activity} và {@link
46android.app.Fragment}.</li>
47    <li>Chúng cung cấp khả năng tải dữ liệu không đồng bộ.</li>
48    <li>Chúng theo dõi nguồn dữ liệu của mình và chuyển giao kết quả mới khi nội dung
49thay đổi.</li>
50    <li>Chúng tự động kết nối lại với con chạy của trình tải cuối cùng khi được
51tạo lại sau khi cấu hình thay đổi. Vì thế, chúng không cần truy vấn lại dữ liệu
52của mình.</li>
53  </ul>
54
55<h2 id="summary">Tổng quan về API Trình tải</h2>
56
57<p>Có nhiều lớp và giao diện có thể có liên quan trong khi sử dụng
58các trình tải trong một ứng dụng. Chúng được tóm tắt trong bảng này.</p>
59
60<table>
61  <tr>
62    <th>Lớp/Giao diện</th>
63    <th>Mô tả</th>
64  </tr>
65  <tr>
66    <td>{@link android.app.LoaderManager}</td>
67    <td>Một lớp tóm tắt được liên kết với {@link android.app.Activity} hoặc
68{@link android.app.Fragment} để quản lý một hoặc nhiều thực thể {@link
69android.content.Loader}. Nó giúp ứng dụng quản lý
70các thao tác chạy lâu hơn cùng với vòng đời {@link android.app.Activity}
71hoặc {@link android.app.Fragment}; công dụng phổ biến nhất của lớp này là khi dùng với
72{@link android.content.CursorLoader}, tuy nhiên, các ứng dụng được tự do ghi
73trình tải của chính mình để tải các kiểu dữ liệu khác.
74    <br />
75    <br />
76    Chỉ có một {@link android.app.LoaderManager} trên mỗi hoạt động hoặc phân đoạn. Nhưng một {@link android.app.LoaderManager} có thể có
77nhiều trình tải.</td>
78  </tr>
79  <tr>
80    <td>{@link android.app.LoaderManager.LoaderCallbacks}</td>
81    <td>Một giao diện gọi lại để một máy khách tương tác với {@link
82android.app.LoaderManager}. Ví dụ, bạn sử dụng phương pháp gọi lại {@link
83android.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()}
84để tạo một trình tải mới.</td>
85  </tr>
86  <tr>
87    <td>{@link android.content.Loader}</td>
88    <td>Một lớp tóm tắt có vai trò thực hiện việc tải dữ liệu không đồng bộ. Đây là
89lớp cơ bản cho một trình tải. Thông thường, bạn sẽ sử dụng {@link
90android.content.CursorLoader}, nhưng bạn có thể triển khai lớp con của chính mình. Trong khi
91các trình tải đang hoạt động, chúng sẽ theo dõi nguồn dữ liệu của mình và chuyển giao
92kết quả mới khi nội dung thay đổi. </td>
93  </tr>
94  <tr>
95    <td>{@link android.content.AsyncTaskLoader}</td>
96    <td>Trình tải tóm tắt có chức năng cung cấp {@link android.os.AsyncTask} để thực hiện công việc.</td>
97  </tr>
98  <tr>
99    <td>{@link android.content.CursorLoader}</td>
100    <td>Một lớp con của {@link android.content.AsyncTaskLoader} có chức năng truy vấn
101{@link android.content.ContentResolver} và trả về một {@link
102android.database.Cursor}. Lớp này triển khai giao thức {@link
103android.content.Loader} theo một cách chuẩn hóa để truy vấn các con chạy,
104xây dựng trên {@link android.content.AsyncTaskLoader} để thực hiện truy vấn con chạy
105trên một luồng nền sao cho nó không chặn UI của ứng dụng. Sử dụng
106trình tải này là cách tốt nhất để tải dữ liệu không đồng bộ từ một {@link
107android.content.ContentProvider}, thay vì phải thực hiện một truy vấn được quản lý thông qua
108phân đoạn hoặc các API của hoạt động.</td>
109  </tr>
110</table>
111
112<p>Các lớp và giao diện trong bảng trên là những thành phần thiết yếu
113mà bạn sẽ sử dụng để triển khai một trình tải trong ứng dụng của mình. Bạn sẽ không cần tất cả chúng
114cho từng trình tải mà bạn tạo lập, nhưng bạn sẽ luôn cần một tham chiếu tới {@link
115android.app.LoaderManager} để khởi tạo một trình tải và triển khai
116một lớp {@link android.content.Loader} chẳng hạn như {@link
117android.content.CursorLoader}. Các phần sau đây trình bày với bạn cách sử dụng những
118lớp và giao diện này trong một ứng dụng.</p>
119
120<h2 id ="app">Sử dụng các Trình tải trong một Ứng dụng</h2>
121<p>Phần này mô tả cách sử dụng các trình tải trong một ứng dụng Android. Một
122ứng dụng sử dụng trình tải thường bao gồm:</p>
123<ul>
124  <li>Một {@link android.app.Activity} hoặc {@link android.app.Fragment}.</li>
125  <li>Một thực thể của {@link android.app.LoaderManager}.</li>
126  <li>Một {@link android.content.CursorLoader} để tải dữ liệu được dự phòng bởi một {@link
127android.content.ContentProvider}. Hoặc cách khác, bạn có thể triển khai lớp con
128của {@link android.content.Loader} hoặc {@link android.content.AsyncTaskLoader} của chính mình để tải
129dữ liệu từ một số nguồn khác.</li>
130  <li>Một triển khai cho {@link android.app.LoaderManager.LoaderCallbacks}.
131Đây là nơi bạn tạo trình tải mới và quản lý các tham chiếu của mình tới các
132trình tải hiện có.</li>
133<li>Một cách để hiển thị dữ liệu của trình tải, chẳng hạn như {@link
134android.widget.SimpleCursorAdapter}.</li>
135  <li>Một nguồn dữ liệu, chẳng hạn như một {@link android.content.ContentProvider}, khi sử dụng một
136{@link android.content.CursorLoader}.</li>
137</ul>
138<h3 id="starting">Khởi động một Trình tải</h3>
139
140<p>{@link android.app.LoaderManager} quản lý một hoặc nhiều thực thể {@link
141android.content.Loader} trong một {@link android.app.Activity} hoặc
142{@link android.app.Fragment}. Chỉ có một {@link
143android.app.LoaderManager} trên mỗi hoạt động hoặc phân đoạn.</p>
144
145<p>Thông thường, bạn
146sẽ khởi tạo một {@link android.content.Loader} bên trong phương pháp {@link
147android.app.Activity#onCreate onCreate()} của hoạt động, hoặc trong phương pháp
148{@link android.app.Fragment#onActivityCreated onActivityCreated()} của phân đoạn. Bạn
149làm điều này như sau:</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>Phương pháp {@link android.app.LoaderManager#initLoader initLoader()} sẽ lấy những
156tham số sau:</p>
157<ul>
158  <li>Một ID duy nhất xác định trình tải. Trong ví dụ này, ID là 0.</li>
159<li>Các tham đối tùy chọn để cung cấp cho trình tải khi
160xây dựng (<code>null</code> trong ví dụ này).</li>
161
162<li>Triển khai {@link android.app.LoaderManager.LoaderCallbacks}, phương pháp mà
163{@link android.app.LoaderManager} gọi để báo cáo các sự kiện trình tải. Trong ví dụ này
164, lớp cục bộ triển khai giao diện {@link
165android.app.LoaderManager.LoaderCallbacks}, vì thế nó chuyển một tham chiếu
166tới chính nó, {@code this}.</li>
167</ul>
168<p>Lệnh gọi {@link android.app.LoaderManager#initLoader initLoader()} đảm bảo rằng một trình tải
169được khởi tạo và hiện hoạt. Nó có hai kết quả có thể xảy ra:</p>
170<ul>
171  <li>Nếu trình tải được quy định bởi ID đã tồn tại, trình tải được tạo lập cuối cùng
172sẽ được sử dụng lại.</li>
173  <li>Nếu trình tải được quy định bởi ID <em>không</em> tồn tại,
174{@link android.app.LoaderManager#initLoader initLoader()} sẽ kích khởi phương pháp
175{@link android.app.LoaderManager.LoaderCallbacks}{@link android.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()}.
176Đây là nơi bạn triển khai mã để khởi tạo và trả về một trình tải mới.
177Để bàn thêm, hãy xem phần <a href="#onCreateLoader">onCreateLoader</a>.</li>
178</ul>
179<p>Dù trong trường hợp nào, triển khai {@link android.app.LoaderManager.LoaderCallbacks}
180đã cho được liên kết với trình tải, và sẽ được gọi khi
181trạng thái của trình tải thay đổi.  Nếu tại điểm thực hiện lệnh gọi này, hàm gọi đang trong trạng thái
182được khởi động của nó, và trình tải được yêu cầu đã tồn tại và đã khởi tạo
183dữ liệu của nó, khi đó hệ thống sẽ gọi {@link
184android.app.LoaderManager.LoaderCallbacks#onLoadFinished onLoadFinished()}
185ngay lập tức (trong khi {@link android.app.LoaderManager#initLoader initLoader()}),
186vì thế bạn phải sẵn sàng khi điều này xảy ra. Xem <a href="#onLoadFinished">
187onLoadFinished</a> để thảo luận thêm về lệnh gọi lại này</p>
188
189<p>Lưu ý rằng phương pháp {@link android.app.LoaderManager#initLoader initLoader()}
190sẽ trả về {@link android.content.Loader} đã được tạo lập, nhưng bạn không
191cần bắt lại một tham chiếu tới nó. {@link android.app.LoaderManager} tự động quản lý
192vòng đời của trình tải. {@link android.app.LoaderManager}
193khởi động và dừng tải khi cần và duy trì trạng thái của trình tải
194và nội dung đi kèm của nó. Như hàm ý, bạn hiếm khi tương tác trực tiếp với các trình tải
195(thông qua một ví dụ về việc sử dụng các phương pháp trình tải để tinh chỉnh hành vi
196của một trình tải, hãy xem ví dụ <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LoaderThrottle.html"> LoaderThrottle</a>).
197Bạn thường sử dụng nhất là các phương pháp {@link
198android.app.LoaderManager.LoaderCallbacks} để can thiệp vào tiến trình tải
199khi diễn ra một sự kiện đặc biệt. Để thảo luận thêm về chủ đề này, hãy xem phần <a href="#callback">Sử dụng Phương pháp Gọi lại LoaderManager</a>.</p>
200
201<h3 id="restarting">Khởi động lại một Trình tải</h3>
202
203<p>Khi bạn sử dụng {@link android.app.LoaderManager#initLoader initLoader()}, như
204trình bày bên trên, nó sử dụng một trình tải hiện hữu với ID được quy định nếu có.
205Nếu không có, nó sẽ tạo một trình tải. Nhưng đôi khi bạn muốn bỏ dữ liệu cũ của mình
206và bắt đầu lại.</p>
207
208<p>Để bỏ dữ liệu cũ của mình, hãy sử dụng {@link
209android.app.LoaderManager#restartLoader restartLoader()}. Ví dụ, việc
210triển khai {@link android.widget.SearchView.OnQueryTextListener} này sẽ khởi động lại
211trình tải khi truy vấn của người dùng thay đổi. Trình tải cần được khởi động lại sao cho
212nó có thể sử dụng bộ lọc tìm kiếm được điều chỉnh để thực hiện một truy vấn mới:</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">Sử dụng các Phương pháp Gọi lại LoaderManager</h3>
225
226<p>{@link android.app.LoaderManager.LoaderCallbacks} là một giao diện gọi lại
227cho phép một máy khách tương tác với {@link android.app.LoaderManager}. </p>
228<p>Các trình tải, đặc biệt là {@link android.content.CursorLoader}, được kỳ vọng sẽ
229giữ lại dữ liệu của chúng sau khi bị dừng. Điều này cho phép ứng dụng giữ lại
230dữ liệu của chúng qua hoạt động hoặc các phương pháp {@link android.app.Activity#onStop
231onStop()} và {@link android.app.Activity#onStart onStart()} của phân đoạn, sao cho khi
232người dùng quay lại một ứng dụng, họ không phải chờ dữ liệu
233tải lại. Bạn sử dụng các phương pháp {@link android.app.LoaderManager.LoaderCallbacks}
234khi cần biết khi nào thì nên tạo một trình tải mới, và để thông báo với ứng dụng khi nào
235 thì đến lúc để dừng sử dụng dữ liệu của một trình tải.</p>
236
237<p>{@link android.app.LoaderManager.LoaderCallbacks} bao gồm những phương pháp
238sau:</p>
239<ul>
240  <li>{@link android.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()}  —
241Khởi tạo và trả về một {@link android.content.Loader} mới cho ID đã cho.
242</li></ul>
243<ul>
244  <li> {@link android.app.LoaderManager.LoaderCallbacks#onLoadFinished onLoadFinished()}
245— Được gọi khi một trình tải được tạo trước đó đã hoàn tất việc tải.
246</li></ul>
247<ul>
248  <li>{@link android.app.LoaderManager.LoaderCallbacks#onLoaderReset onLoaderReset()}
249    — Được gọi khi một trình tải được tạo trước đó đang được đặt lại, vì thế mà khiến dữ liệu
250của nó không sẵn có.
251</li>
252</ul>
253<p>Những phương pháp này được mô tả chi tiết hơn trong các phần sau.</p>
254
255<h4 id ="onCreateLoader">onCreateLoader</h4>
256
257<p>Khi bạn định truy cập một trình tải (ví dụ, thông qua {@link
258android.app.LoaderManager#initLoader initLoader()}), nó kiểm tra xem
259trình tải được quy định bởi ID có tồn tại không. Nếu không, nó sẽ kích khởi phương pháp {@link
260android.app.LoaderManager.LoaderCallbacks} {@link
261android.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()}. Đây
262là lúc bạn tạo một trình tải mới. Thông thường sẽ có một {@link
263android.content.CursorLoader}, nhưng bạn có thể triển khai lớp con {@link
264android.content.Loader} của chính mình. </p>
265
266<p>Trong ví dụ này, phương pháp gọi lại {@link
267android.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()}
268sẽ tạo một {@link android.content.CursorLoader}. Bạn phải xây dựng
269{@link android.content.CursorLoader} bằng cách sử dụng phương pháp hàm dựng của nó mà yêu cầu
270trọn bộ thông tin cần thiết để thực hiện một truy vấn tới {@link
271android.content.ContentProvider}. Cụ thể, nó cần:</p>
272<ul>
273  <li><em>uri</em> — URI của nội dung cần truy xuất. </li>
274  <li><em>dự thảo</em> — Một danh sách các cột sẽ trả về. Việc chuyển
275<code>null</code> sẽ trả về tất cả cột, điều này không hiệu quả. </li>
276  <li><em>lựa chọn</em> — Một bộ lọc khai báo các hàng nào sẽ trả về,
277có định dạng như một mệnh đề SQL WHERE (không gồm chính mệnh đề WHERE). Việc chuyển
278<code>null</code> sẽ trả về tất cả hàng cho URI đã cho. </li>
279  <li><em>selectionArgs</em> — Bạn có thể thêm ?s vào lựa chọn,
280chúng sẽ được thay thế bằng các giá trị từ <em>selectionArgs</em>, theo thứ tự xuất hiện trong
281lựa chọn. Giá trị sẽ được gắn kết thành các Xâu. </li>
282  <li><em>sortOrder</em> — Cách sắp xếp thứ tự các hàng, được định dạng như một mệnh đề SQL
283ORDER BY (không bao gồm chính mệnh đề ORDER BY). Việc chuyển <code>null</code> sẽ
284sử dụng thứ tự sắp xếp mặc định, điều này có thể dẫn đến kết quả không theo thứ tự.</li>
285</ul>
286<p>Ví dụ:</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>Phương pháp này được gọi khi một trình tải được tạo trước đó đã hoàn thành việc tải của mình.
316Phương pháp này được bảo đảm sẽ được gọi trước khi giải phóng dữ liệu cuối cùng
317được cung cấp cho trình tải này.  Tại điểm này, bạn nên loại bỏ mọi trường hợp sử dụng
318dữ liệu cũ (do nó sẽ được giải phóng sớm), nhưng không nên
319tự mình giải phóng dữ liệu do trình tải sở hữu dữ liệu và sẽ đảm nhận việc này.</p>
320
321
322<p>Trình tải sẽ giải phóng dữ liệu sau khi nó biết ứng dụng đang không còn
323sử dụng nó nữa.  Ví dụ, nếu dữ liệu là một con chạy từ một {@link
324android.content.CursorLoader}, bạn không nên tự mình gọi {@link
325android.database.Cursor#close close()} trên dữ liệu đó. Nếu con chạy đang được đặt
326trong một {@link android.widget.CursorAdapter}, bạn nên sử dụng phương pháp {@link
327android.widget.SimpleCursorAdapter#swapCursor swapCursor()} sao cho
328 {@link android.database.Cursor} cũ không bị đóng. Ví dụ:</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>Phương pháp này được gọi khi một trình tải được tạo trước đó đang được đặt lại, vì thế mà khiến
344dữ liệu của nó không sẵn có. Lệnh gọi lại này cho phép bạn tìm hiểu xem khi nào thì dữ liệu
345sẽ được giải phóng để bạn có thể loại bỏ tham chiếu của mình tới nó.  </p>
346<p>Sự triển khai này gọi ra
347{@link android.widget.SimpleCursorAdapter#swapCursor swapCursor()}
348với một giá trị <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">Ví dụ</h2>
364
365<p>Lấy một ví dụ, sau đây là triển khai đầy đủ của {@link
366android.app.Fragment} có chức năng hiển thị một {@link android.widget.ListView} chứa
367kết quả của một truy vấn đối với trình cung cấp nội dung danh bạ. Nó sử dụng một {@link
368android.content.CursorLoader} để quản lý truy vấn trên trình cung cấp.</p>
369
370<p>Để một ứng dụng truy cập danh bạ của một người dùng, như minh họa trong ví dụ này, bản kê khai
371của nó phải bao gồm quyền
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">Thêm Ví dụ</h3>
481
482<p>Có một vài mẫu khác trong <strong>ApiDemos</strong> để
483minh họa cách sử dụng các trình tải:</p>
484<ul>
485  <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LoaderCursor.html">
486LoaderCursor</a> — Một phiên bản hoàn chỉnh của
487đoạn mã HTML trình bày ở trên.</li>
488  <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LoaderThrottle.html"> LoaderThrottle</a> — Một ví dụ về cách sử dụng điều chỉnh để giảm
489số truy vấn mà một trình cung cấp nội dung thực hiện khi dữ liệu của nó thay đổi.</li>
490</ul>
491
492<p>Để biết thông tin về việc tải xuống và cài đặt các mẫu SDK, hãy xem phần <a href="http://developer.android.com/resources/samples/get.html"> Tải
493Mẫu</a>. </p>
494
495