1page.title=Thiết đặt
2page.tags=preference,preferenceactivity,preferencefragment
3
4@jd:body
5
6
7<div id="qv-wrapper">
8<div id="qv">
9
10<h2>Trong tài liệu này</h2>
11<ol>
12  <li><a href="#Overview">Tổng quan</a>
13    <ol>
14      <li><a href="#SettingTypes">Tùy chọn</a></li>
15    </ol>
16  </li>
17  <li><a href="#DefiningPrefs">Định nghĩa Tùy chọn trong XML</a>
18    <ol>
19      <li><a href="#Groups">Tạo nhóm thiết đặt</a></li>
20      <li><a href="#Intents">Sử dụng ý định</a></li>
21    </ol>
22  </li>
23  <li><a href="#Activity">Tạo một Hoạt động Tùy chọn</a></li>
24  <li><a href="#Fragment">Sử dụng Phân đoạn Tùy chọn</a></li>
25  <li><a href="#Defaults">Thiết đặt Giá trị Mặc định</a></li>
26  <li><a href="#PreferenceHeaders">Sử dụng Tiêu đề Tùy chọn</a>
27    <ol>
28      <li><a href="#CreateHeaders">Tạo tệp tiêu đề</a></li>
29      <li><a href="#DisplayHeaders">Hiển thị tiêu đề</a></li>
30      <li><a href="#BackCompatHeaders">Hỗ trợ các phiên bản cũ hơn với tiêu đề tùy chọn</a></li>
31    </ol>
32  </li>
33  <li><a href="#ReadingPrefs">Đọc Tùy chọn</a>
34    <ol>
35      <li><a href="#Listening">Theo dõi thay đổi tùy chọn</a></li>
36    </ol>
37  </li>
38  <li><a href="#NetworkUsage">Quản lý Sử dụng Mạng</a></li>
39  <li><a href="#Custom">Xây dựng một Thiết đặt Tùy chỉnh</a>
40    <ol>
41      <li><a href="#CustomSelected">Quy định một giao diện người dùng</a></li>
42      <li><a href="#CustomSave">Lưu giá trị của thiết đặt</a></li>
43      <li><a href="#CustomInitialize">Khởi tạo giá trị hiện tại</a></li>
44      <li><a href="#CustomDefault">Cung cấp một giá trị mặc định</a></li>
45      <li><a href="#CustomSaveState">Lưu và khôi phục trạng thái của Tùy chọn</a></li>
46    </ol>
47  </li>
48</ol>
49
50<h2>Lớp khóa</h2>
51<ol>
52  <li>{@link android.preference.Preference}</li>
53  <li>{@link android.preference.PreferenceActivity}</li>
54  <li>{@link android.preference.PreferenceFragment}</li>
55</ol>
56
57
58<h2>Xem thêm</h2>
59<ol>
60  <li><a href="{@docRoot}design/patterns/settings.html">Hướng dẫn thiết kế Thiết đặt</a></li>
61</ol>
62</div>
63</div>
64
65
66
67
68<p>Ứng dụng thường bao gồm những thiết đặt cho phép người dùng sửa đổi các tính năng và hành vi của ứng dụng. Ví
69dụ, một số ứng dụng cho phép người dùng quy định xem thông báo có được kích hoạt hay không hoặc quy định tần suất
70ứng dụng sẽ đồng bộ dữ liệu với đám mây.</p>
71
72<p>Nếu muốn cung cấp thiết đặt cho ứng dụng của mình, bạn nên sử dụng
73các API {@link android.preference.Preference} của Android để xây dựng một giao diện phù hợp với
74trải nghiệm người dùng trong các ứng dụng Android khác (bao gồm thiết đặt hệ thống). Tài liệu này mô tả
75cách xây dựng thiết đặt ứng dụng của bạn bằng cách sử dụng các API {@link android.preference.Preference}.</p>
76
77<div class="note design">
78<p><strong>Thiết kế Thiết đặt</strong></p>
79  <p>Để biết thông tin về cách thiết kế thiết đặt của bạn, hãy đọc hướng dẫn thiết kế <a href="{@docRoot}design/patterns/settings.html">Thiết đặt</a>.</p>
80</div>
81
82
83<img src="{@docRoot}images/ui/settings/settings.png" alt="" width="435" />
84<p class="img-caption"><strong>Hình 1.</strong> Ảnh chụp màn hình từ thiết đặt của ứng dụng
85Messaging trên Android. Chọn một mục được định nghĩa bởi một {@link android.preference.Preference}
86sẽ mở ra một giao diện để thay đổi thiết đặt.</p>
87
88
89
90
91<h2 id="Overview">Tổng quan</h2>
92
93<p>Thay vì sử dụng các đối tượng {@link android.view.View} để xây dựng giao diện người dùng, thiết đặt được
94xây dựng bằng cách sử dụng các lớp con khác nhau của lớp {@link android.preference.Preference} mà bạn
95khai báo trong một tệp XML.</p>
96
97<p>Đối tượng {@link android.preference.Preference} là một khối dựng cho một thiết đặt
98đơn lẻ. Mỗi {@link android.preference.Preference} xuất hiện như một mục trong một danh sách và cung cấp
99UI phù hợp để người dùng sửa đổi thiết đặt. Ví dụ, một {@link
100android.preference.CheckBoxPreference} tạo một mục danh sách hiển thị một hộp kiểm, và một {@link
101android.preference.ListPreference} tạo một mục mở ra một hộp thoại với danh sách lựa chọn.</p>
102
103<p>Mỗi {@link android.preference.Preference} mà bạn thêm có một cặp khóa-giá trị tương ứng mà
104hệ thống sử dụng để lưu thiết đặt trong một tệp {@link android.content.SharedPreferences}
105mặc định cho thiết đặt của ứng dụng của bạn. Khi người dùng thay đổi một thiết đặt, hệ thống sẽ cập nhật giá trị
106tương ứng trong tệp {@link android.content.SharedPreferences} cho bạn. Lần duy nhất mà bạn nên
107trực tiếp tương tác với tệp {@link android.content.SharedPreferences} được liên kết đó là khi bạn
108cần đọc giá trị để xác định xem hành vi ứng dụng của mình có được dựa trên thiết đặt của người dùng không.</p>
109
110<p>Giá trị được lưu trong {@link android.content.SharedPreferences} cho từng thiết đặt có thể là một trong các kiểu dữ liệu
111sau:</p>
112
113<ul>
114  <li>Boolean</li>
115  <li>Float</li>
116  <li>Int</li>
117  <li>Long</li>
118  <li>String</li>
119  <li>String {@link java.util.Set}</li>
120</ul>
121
122<p>Vì thiết đặt của ứng dụng của bạn được xây dựng bằng cách sử dụng các đối tượng {@link android.preference.Preference}
123thay vì đối tượng
124{@link android.view.View}, bạn nên sử dụng một lớp con {@link android.app.Activity} hoặc
125{@link android.app.Fragment} chuyên dụng để hiển thị thiết đặt danh sách:</p>
126
127<ul>
128  <li>Nếu ứng dụng của bạn hỗ trợ các phiên bản Android cũ hơn 3.0 (API mức 10 và thấp hơn), bạn phải
129xây dựng hoạt động như một phần mở rộng của lớp {@link android.preference.PreferenceActivity}.</li>
130  <li>Trên phiên bản Android 3.0 trở lên, thay vào đó, bạn nên sử dụng một {@link android.app.Activity}
131truyền thống nơi lưu giữ {@link android.preference.PreferenceFragment} để hiển thị thiết đặt ứng dụng của bạn.
132Tuy nhiên, bạn cũng có thể sử dụng {@link android.preference.PreferenceActivity} để tạo một bố trí hai bảng
133cho màn hình lớn khi bạn có nhiều nhóm thiết đặt.</li>
134</ul>
135
136<p>Cách thiết đặt {@link android.preference.PreferenceActivity} của bạn và các thực thể của {@link
137android.preference.PreferenceFragment} được trình bày trong các phần về <a href="#Activity">Tạo một Hoạt động Tùy chọn</a> và <a href="#Fragment">Sử dụng
138Phân đoạn Tùy chọn</a>.</p>
139
140
141<h3 id="SettingTypes">Tùy chọn</h3>
142
143<p>Mọi thiết đặt cho ứng dụng của bạn đều được biểu diễn bởi một lớp con cụ thể của lớp {@link
144android.preference.Preference}. Mỗi lớp con lại bao gồm một tập hợp các tính chất cốt lõi cho phép bạn
145quy định những thứ như tiêu đề cho thiết đặt và giá trị mặc định. Mỗi lớp con cũng cung cấp
146các tính chất và giao diện người dùng chuyên dụng của chính nó. Ví dụ, hình 1 mình họa một ảnh chụp màn hình từ thiết đặt của ứng dụng
147Messaging. Mỗi mục danh sách trong màn hình thiết đặt được hỗ trợ bởi một đối tượng {@link
148android.preference.Preference} khác nhau.</p>
149
150<p>Sau đây là một số tùy chọn phổ biến nhất:</p>
151
152<dl>
153  <dt>{@link android.preference.CheckBoxPreference}</dt>
154  <dd>Hiển thị một mục kèm một hộp kiểm cho thiết đặt hoặc được kích hoạt hoặc bị vô hiệu hóa. Giá trị
155được lưu là một boolean (<code>true</code> nếu nó được chọn).</dd>
156
157  <dt>{@link android.preference.ListPreference}</dt>
158  <dd>Mở một hộp thoại kèm danh sách nút chọn một. Giá trị được lưu
159có thể là bất kỳ loại giá trị được hỗ trợ nào (liệt kê bên trên).</dd>
160
161  <dt>{@link android.preference.EditTextPreference}</dt>
162  <dd>Mở một hộp thoại kèm một widget {@link android.widget.EditText}. Giá trị được lưu là một {@link
163java.lang.String}.</dd>
164</dl>
165
166<p>Xem lớp {@link android.preference.Preference} để biết danh sách tất cả các lớp con khác và tính chất
167tương ứng của chúng.</p>
168
169<p>Dĩ nhiên, các lớp tích hợp không đáp ứng mọi nhu cầu và ứng dụng của bạn có thể yêu cầu
170lớp con chuyên dụng hơn. Ví dụ, nền tảng này hiện chưa cung cấp một lớp {@link
171android.preference.Preference} cho việc chọn một số hay ngày. Vì thế, bạn có thể cần phải định nghĩa
172lớp con {@link android.preference.Preference} của chính mình. Để được trợ giúp khi làm vậy, hãy xem phần về <a href="#Custom">Xây dựng Thiết đặt Tùy chỉnh</a>.</p>
173
174
175
176<h2 id="DefiningPrefs">Định nghĩa Tùy chọn trong XML</h2>
177
178<p>Mặc dù bạn có thể khởi tạo các đối tượng {@link android.preference.Preference} mới vào thời gian chạy, bạn
179nên định nghĩa danh sách các thiết đặt của mình trong XML kèm một phân cấp của các đối tượng {@link android.preference.Preference}
180. Việc sử dụng một tệp XML để định nghĩa bộ sưu tập thiết đặt của bạn sẽ được ưu tiên vì tệp
181cung cấp một cấu trúc dễ đọc, cập nhật đơn giản. Bên cạnh đó, các thiết đặt ứng dụng của bạn thường được
182xác định trước, mặc dù bạn vẫn có thể sửa đổi bộ sưu tập vào thời gian chạy.</p>
183
184<p>Mỗi lớp con {@link android.preference.Preference} có thể được khai báo bằng một phần tử XML mà
185khớp với tên lớp đó, chẳng hạn như {@code &lt;CheckBoxPreference&gt;}.</p>
186
187<p>Bạn phải lưu tệp XML trong thư mục {@code res/xml/}. Mặc dù bạn có thể đặt tên tệp là
188bất cứ thứ gì mình muốn, nó thường được đặt tên là{@code preferences.xml}. Bạn thường chỉ cần một tệp,
189bởi các nhánh trong phân cấp (mà mở danh sách thiết đặt của riêng chúng) sẽ được khai báo bằng cách sử dụng các thực thể
190lồng nhau của {@link android.preference.PreferenceScreen}.</p>
191
192<p class="note"><strong>Lưu ý:</strong> Nếu bạn muốn tạo một bố trí đa bảng cho thiết đặt
193của mình, vậy bạn nên tách riêng các tệp XML cho từng phân đoạn.</p>
194
195<p>Node gốc cho tệp XML phải là một phần tử {@link android.preference.PreferenceScreen
196&lt;PreferenceScreen&gt;}. Trong phần tử này là nơi bạn thêm từng {@link
197android.preference.Preference}. Từng phần tử con mà bạn thêm vào trong phần tử
198{@link android.preference.PreferenceScreen &lt;PreferenceScreen&gt;} sẽ xuất hiện như một mục
199đơn lẻ trong danh sách thiết đặt.</p>
200
201<p>Ví dụ:</p>
202
203<pre>
204&lt;?xml version="1.0" encoding="utf-8"?>
205&lt;PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
206    &lt;CheckBoxPreference
207        android:key="pref_sync"
208        android:title="@string/pref_sync"
209        android:summary="@string/pref_sync_summ"
210        android:defaultValue="true" />
211    &lt;ListPreference
212        android:dependency="pref_sync"
213        android:key="pref_syncConnectionType"
214        android:title="@string/pref_syncConnectionType"
215        android:dialogTitle="@string/pref_syncConnectionType"
216        android:entries="@array/pref_syncConnectionTypes_entries"
217        android:entryValues="@array/pref_syncConnectionTypes_values"
218        android:defaultValue="@string/pref_syncConnectionTypes_default" />
219&lt;/PreferenceScreen>
220</pre>
221
222<p>Trong ví dụ này, có một {@link android.preference.CheckBoxPreference} và một {@link
223android.preference.ListPreference}. Cả hai mục đều bao gồm ba thuộc tính sau:</p>
224
225<dl>
226  <dt>{@code android:key}</dt>
227  <dd>Thuộc tính này được yêu cầu cho các tùy chọn duy trì một giá trị dữ liệu. Nó quy định khóa
228(xâu) duy nhất mà hệ thống sử dụng khi lưu giá trị của thiết đặt này trong {@link
229android.content.SharedPreferences}.
230  <p>Các thực thể duy nhất mà thuộc tính này không <em>được yêu cầu</em> là khi tùy chọn là một
231{@link android.preference.PreferenceCategory} hoặc {@link android.preference.PreferenceScreen}, hoặc
232tùy chọn quy định một {@link android.content.Intent} để gọi ra (bằng phần tử <a href="#Intents">{@code &lt;intent&gt;}</a>) hoặc {@link android.app.Fragment} để hiển thị (bằng thuộc tính <a href="{@docRoot}reference/android/preference/Preference.html#attr_android:fragment">{@code
233android:fragment}</a>).</p>
234  </dd>
235  <dt>{@code android:title}</dt>
236  <dd>Thuộc tính này cung cấp một tên hiển thị với người dùng cho thiết đặt.</dd>
237  <dt>{@code android:defaultValue}</dt>
238  <dd>Nó quy định giá trị ban đầu mà hệ thống nên đặt trong tệp {@link
239android.content.SharedPreferences}. Bạn nên cung cấp một giá trị mặc định cho tất cả
240thiết đặt.</dd>
241</dl>
242
243<p>Để biết thông tin về tất cả thuộc tính được hỗ trợ khác, hãy xem tài liệu {@link
244android.preference.Preference} (và lớp con tương ứng).</p>
245
246
247<div class="figure" style="width:300px">
248  <img src="{@docRoot}images/ui/settings/settings-titles.png" alt="" />
249  <p class="img-caption"><strong>Hình 2.</strong> Thiết đặt thể loại
250    có tiêu đề. <br/><b>1.</b> Thể loại được quy định bởi phần tử {@link
251android.preference.PreferenceCategory &lt;PreferenceCategory&gt;}. <br/><b>2.</b> Tiêu đề
252được quy định bằng thuộc tính {@code android:title}.</p>
253</div>
254
255
256<p>Khi danh sách thiết đặt của bạn vượt quá khoảng 10 mục, bạn có thể muốn thêm tiêu đề để
257định nghĩa các nhóm thiết đặt hoặc hiển thị các nhóm đó trong một
258màn hình riêng. Những tùy chọn này được mô tả trong các phần sau.</p>
259
260
261<h3 id="Groups">Tạo nhóm thiết đặt</h3>
262
263<p>Nếu bạn trình bày một danh sách từ 10 thiết đặt trở lên, người dùng
264có thể gặp khó khăn trong việc dò tìm, hiểu và xử lý chúng. Bạn có thể khắc phục điều này bằng cách
265chia một số hoặc tất cả thiết đặt thành các nhóm, qua đó biến một danh sách dài thành nhiều
266danh sách ngắn hơn. Một nhóm các thiết đặt có liên quan có thể được trình bày bằng một trong hai cách:</p>
267
268<ul>
269  <li><a href="#Titles">Sử dụng tiêu đề</a></li>
270  <li><a href="#Subscreens">Sử dụng màn hình con</a></li>
271</ul>
272
273<p>Bạn có thể sử dụng một hoặc cả hai kỹ thuật tạo nhóm này để sắp xếp các thiết đặt cho ứng dụng của mình. Khi
274quyết định sử dụng cái nào và làm thế nào để chia các thiết đặt của mình, bạn nên tuân theo các hướng dẫn trong tài liệu hướng dẫn
275<a href="{@docRoot}design/patterns/settings.html">Thiết đặt</a> của Thiết kế Android.</p>
276
277
278<h4 id="Titles">Sử dụng tiêu đề</h4>
279
280<p>Nếu bạn muốn cung cấp các thanh chia có tiêu đề giữa các nhóm thiết đặt (như minh họa trong hình 2),
281hãy đặt từng nhóm đối tượng {@link android.preference.Preference} vào bên trong một {@link
282android.preference.PreferenceCategory}.</p>
283
284<p>Ví dụ:</p>
285
286<pre>
287&lt;PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
288    &lt;PreferenceCategory
289        android:title="&#64;string/pref_sms_storage_title"
290        android:key="pref_key_storage_settings">
291        &lt;CheckBoxPreference
292            android:key="pref_key_auto_delete"
293            android:summary="&#64;string/pref_summary_auto_delete"
294            android:title="&#64;string/pref_title_auto_delete"
295            android:defaultValue="false"... />
296        &lt;Preference
297            android:key="pref_key_sms_delete_limit"
298            android:dependency="pref_key_auto_delete"
299            android:summary="&#64;string/pref_summary_delete_limit"
300            android:title="&#64;string/pref_title_sms_delete"... />
301        &lt;Preference
302            android:key="pref_key_mms_delete_limit"
303            android:dependency="pref_key_auto_delete"
304            android:summary="&#64;string/pref_summary_delete_limit"
305            android:title="&#64;string/pref_title_mms_delete" ... />
306    &lt;/PreferenceCategory>
307    ...
308&lt;/PreferenceScreen>
309</pre>
310
311
312<h4 id="Subscreens">Sử dụng màn hình con</h4>
313
314<p>Nếu bạn muốn đặt các nhóm thiết đặt vào một màn hình con (như minh họa trong hình 3), hãy đặt nhóm
315các đối tượng {@link android.preference.Preference} vào bên trong một {@link
316android.preference.PreferenceScreen}.</p>
317
318<img src="{@docRoot}images/ui/settings/settings-subscreen.png" alt="" />
319<p class="img-caption"><strong>Hình 3.</strong> Màn hình con thiết đặt. Phần tử {@code
320&lt;PreferenceScreen&gt;} sẽ tạo
321một mục mà, khi được chọn, nó sẽ mở ra một danh sách riêng để hiển thị các thiết đặt lồng nhau.</p>
322
323<p>Ví dụ:</p>
324
325<pre>
326&lt;PreferenceScreen  xmlns:android="http://schemas.android.com/apk/res/android">
327    &lt;!-- opens a subscreen of settings -->
328    &lt;PreferenceScreen
329        android:key="button_voicemail_category_key"
330        android:title="&#64;string/voicemail"
331        android:persistent="false">
332        &lt;ListPreference
333            android:key="button_voicemail_provider_key"
334            android:title="&#64;string/voicemail_provider" ... />
335        &lt;!-- opens another nested subscreen -->
336        &lt;PreferenceScreen
337            android:key="button_voicemail_setting_key"
338            android:title="&#64;string/voicemail_settings"
339            android:persistent="false">
340            ...
341        &lt;/PreferenceScreen>
342        &lt;RingtonePreference
343            android:key="button_voicemail_ringtone_key"
344            android:title="&#64;string/voicemail_ringtone_title"
345            android:ringtoneType="notification" ... />
346        ...
347    &lt;/PreferenceScreen>
348    ...
349&lt;/PreferenceScreen>
350</pre>
351
352
353<h3 id="Intents">Sử dụng ý định</h3>
354
355<p>Trong một số trường hợp, bạn có thể muốn một mục tùy chọn mở một hoạt động khác thay vì một
356màn hình thiết đặt, chẳng hạn như một trình duyệt web để xem một trang web. Để gọi ra một {@link
357android.content.Intent} khi người dùng chọn một mục tùy chọn, hãy thêm một phần tử {@code &lt;intent&gt;}
358làm con của phần tử {@code &lt;Preference&gt;} tương ứng.</p>
359
360<p>Ví dụ, sau đây là cách bạn có thể sử dụng một mục tùy chọn để mở một trang web:</p>
361
362<pre>
363&lt;Preference android:title="@string/prefs_web_page" >
364    &lt;intent android:action="android.intent.action.VIEW"
365            android:data="http://www.example.com" />
366&lt;/Preference>
367</pre>
368
369<p>Bạn có thể tạo cả ý định biểu thị và không biểu thị bằng cách sử dụng các thuộc tính sau:</p>
370
371<dl>
372  <dt>{@code android:action}</dt>
373    <dd>Hành động cần gán, theo mỗi phương pháp {@link android.content.Intent#setAction setAction()}
374.</dd>
375  <dt>{@code android:data}</dt>
376    <dd>Dữ liệu cần gán, theo mỗi phương pháp {@link android.content.Intent#setData setData()}.</dd>
377  <dt>{@code android:mimeType}</dt>
378    <dd>Kiểu MIME cần gán, theo mỗi phương pháp {@link android.content.Intent#setType setType()}
379.</dd>
380  <dt>{@code android:targetClass}</dt>
381    <dd>Phần lớp của tên thành phần, theo mỗi phương pháp {@link android.content.Intent#setComponent
382setComponent()}.</dd>
383  <dt>{@code android:targetPackage}</dt>
384    <dd>Phần gói của tên thành phần, theo mỗi phương pháp {@link
385android.content.Intent#setComponent setComponent()}.</dd>
386</dl>
387
388
389
390<h2 id="Activity">Tạo một Hoạt động Tùy chọn</h2>
391
392<p>Để hiển thị thiết đặt của bạn trong một hoạt động, hãy mở rộng lớp {@link
393android.preference.PreferenceActivity}. Đây là phần mở rộng của lớp {@link
394android.app.Activity} truyền thống mà hiển thị một danh sách các thiết đặt dựa trên một phân cấp của các đối tượng {@link
395android.preference.Preference}. {@link android.preference.PreferenceActivity}
396sẽ tự động duy trì các thiết đặt liên kết với từng {@link
397android.preference.Preference} khi người dùng thực hiện một thay đổi.</p>
398
399<p class="note"><strong>Lưu ý:</strong> Nếu bạn đang phát triển ứng dụng của mình cho phiên bản Android 3.0 và
400cao hơn, thay vào đó bạn nên sử dụng {@link android.preference.PreferenceFragment}. Đi đến phần
401tiếp theo về <a href="#Fragment">Sử dụng Phân đoạn Tùy chọn</a>.</p>
402
403<p>Điều quan trọng nhất cần nhớ đó là bạn không được tải một bố trí dạng xem trong khi gọi lại {@link
404android.preference.PreferenceActivity#onCreate onCreate()}. Thay vào đó, bạn hãy gọi {@link
405android.preference.PreferenceActivity#addPreferencesFromResource addPreferencesFromResource()} để
406thêm tùy chọn mà bạn đã khai báo trong một tệp XML vào hoạt động. Ví dụ, sau đây là đoạn mã tối thiểu
407cần thiết cho một {@link android.preference.PreferenceActivity} chức năng:</p>
408
409<pre>
410public class SettingsActivity extends PreferenceActivity {
411    &#64;Override
412    public void onCreate(Bundle savedInstanceState) {
413        super.onCreate(savedInstanceState);
414        addPreferencesFromResource(R.xml.preferences);
415    }
416}
417</pre>
418
419<p>Đây là đoạn mã vừa đủ cho một số ứng dụng bởi ngay khi người dùng sửa đổi một tùy chọn,
420hệ thống sẽ lưu thay đổi đối với tệp {@link android.content.SharedPreferences} mặc định mà các
421thành phần ứng dụng khác của bạn có thể đọc khi bạn cần kiểm tra thiết đặt của người dùng. Tuy nhiên,
422nhiều ứng dụng lại yêu cầu thêm mã để theo dõi những thay đổi xảy ra với các tùy chọn đó.
423Để biết thông tin về việc theo dõi thay đổi trong tệp {@link android.content.SharedPreferences},
424hãy xem phần về <a href="#ReadingPrefs">Đọc Tùy chọn</a>.</p>
425
426
427
428
429<h2 id="Fragment">Sử dụng Phân đoạn Tùy chọn</h2>
430
431<p>Nếu bạn đang phát triển cho phiên bản Android 3.0 (API mức 11) trở lên, bạn nên sử dụng một {@link
432android.preference.PreferenceFragment} để hiển thị danh sách các đối tượng {@link android.preference.Preference}
433của bạn. Bạn có thể thêm một {@link android.preference.PreferenceFragment} vào bất kỳ hoạt động nào&mdash;bạn không cần
434sử dụng {@link android.preference.PreferenceActivity}.</p>
435
436<p><a href="{@docRoot}guide/components/fragments.html">Phân đoạn</a> cung cấp một kiến trúc
437linh hoạt hơn cho ứng dụng của bạn, so với việc sử dụng chỉ các hoạt động, dù loại hoạt động
438mà bạn đang xây dựng là gì. Như vậy, chúng tôi gợi ý bạn sử dụng {@link
439android.preference.PreferenceFragment} để kiểm soát hiển thị các thiết đặt của mình thay cho {@link
440android.preference.PreferenceActivity} khi có thể.</p>
441
442<p>Việc triển khai {@link android.preference.PreferenceFragment} có thể chỉ đơn giản như
443định nghĩa phương pháp {@link android.preference.PreferenceFragment#onCreate onCreate()} để tải một
444tệp tùy chọn bằng {@link android.preference.PreferenceFragment#addPreferencesFromResource
445addPreferencesFromResource()}. Ví dụ:</p>
446
447<pre>
448public static class SettingsFragment extends PreferenceFragment {
449    &#64;Override
450    public void onCreate(Bundle savedInstanceState) {
451        super.onCreate(savedInstanceState);
452
453        // Load the preferences from an XML resource
454        addPreferencesFromResource(R.xml.preferences);
455    }
456    ...
457}
458</pre>
459
460<p>Khi đó, bạn có thể thêm phân đoạn này vào một {@link android.app.Activity} giống như cách mà bạn sẽ làm với bất kỳ
461{@link android.app.Fragment} nào khác. Ví dụ:</p>
462
463<pre>
464public class SettingsActivity extends Activity {
465    &#64;Override
466    protected void onCreate(Bundle savedInstanceState) {
467        super.onCreate(savedInstanceState);
468
469        // Display the fragment as the main content.
470        getFragmentManager().beginTransaction()
471                .replace(android.R.id.content, new SettingsFragment())
472                .commit();
473    }
474}
475</pre>
476
477<p class="note"><strong>Lưu ý:</strong> {@link android.preference.PreferenceFragment} không có một
478đối tượng {@link android.content.Context} của chính nó. Nếu bạn cần một đối tượng {@link android.content.Context}
479, bạn có thể gọi {@link android.app.Fragment#getActivity()}. Tuy nhiên, hãy chắc chắn là chỉ gọi
480{@link android.app.Fragment#getActivity()} khi phân đoạn đó được gắn kèm với một hoạt động. Khi
481phân đoạn chưa được gắn kèm, hoặc bị bỏ gắn kèm trong khi kết thúc vòng đời của nó, {@link
482android.app.Fragment#getActivity()} sẽ trả về rỗng.</p>
483
484
485<h2 id="Defaults">Thiết đặt Giá trị Mặc định</h2>
486
487<p>Tùy chọn mà bạn tạo có thể định nghĩa một số hành vi quan trọng cho ứng dụng của bạn, vì thế
488bạn cần phải khởi tạo tệp {@link android.content.SharedPreferences} kèm theo với các
489giá trị mặc định cho từng {@link android.preference.Preference} khi người dùng lần đầu mở
490ứng dụng của bạn.</p>
491
492<p>Điều đầu tiên bạn phải làm đó là quy định một giá trị mặc định cho từng đối tượng {@link
493android.preference.Preference}
494trong tệp XML của bạn bằng cách sử dụng thuộc tính {@code android:defaultValue}. Giá trị đó có thể là bất kỳ kiểu
495dữ liệu nào mà phù hợp với đối tượng {@link android.preference.Preference} tương ứng. Ví
496dụ:</p>
497
498<pre>
499&lt;!-- default value is a boolean -->
500&lt;CheckBoxPreference
501    android:defaultValue="true"
502    ... />
503
504&lt;!-- default value is a string -->
505&lt;ListPreference
506    android:defaultValue="@string/pref_syncConnectionTypes_default"
507    ... />
508</pre>
509
510<p>Khi đó, từ phương pháp {@link android.app.Activity#onCreate onCreate()} trong hoạt động chính
511&mdash;của ứng dụng của bạn và trong bất kỳ hoạt động nào khác mà thông qua đó người dùng có thể vào ứng dụng của bạn lần
512đầu tiên&mdash;hãy gọi {@link android.preference.PreferenceManager#setDefaultValues
513setDefaultValues()}:</p>
514
515<pre>
516PreferenceManager.setDefaultValues(this, R.xml.advanced_preferences, false);
517</pre>
518
519<p>Việc gọi này trong khi {@link android.app.Activity#onCreate onCreate()} sẽ đảm bảo rằng
520ứng dụng của bạn được khởi tạo phù hợp với các thiết đặt mặc định mà ứng dụng của bạn có thể cần
521đọc để xác định một số hành vi (chẳng hạn như có tải xuống dữ liệu trong khi đang trên
522mạng di động hay không).</p>
523
524<p>Phương pháp này dùng ba tham đối:</p>
525<ul>
526  <li>{@link android.content.Context} ứng dụng của bạn.</li>
527  <li>ID tài nguyên cho tệp XML tùy chọn mà bạn muốn đặt các giá trị mặc định cho.</li>
528  <li>Một boolean cho biết các giá trị mặc định có nên được đặt nhiều hơn một lần hay không.
529<p>Khi tham đối này là <code>false</code>, hệ thống sẽ đặt các giá trị mặc định chỉ khi phương pháp này chưa từng được
530gọi trước đây (hoặc {@link android.preference.PreferenceManager#KEY_HAS_SET_DEFAULT_VALUES}
531trong tệp tùy chọn được chia sẻ giá trị mặc định là sai).</p></li>
532</ul>
533
534<p>Miễn là bạn đặt tham đối thứ ba này thành <code>false</code>, bạn có thể gọi phương pháp này một cách an toàn
535mỗi khi hoạt động của bạn bắt đầu mà không khống chế các tùy chọn đã lưu của người dùng bằng cách đặt lại chúng thành
536mặc định. Tuy nhiên, nếu bạn đặt nó thành <code>true</code>, bạn sẽ khống chế mọi giá trị
537trước đó bằng các giá trị mặc định.</p>
538
539
540
541<h2 id="PreferenceHeaders">Sử dụng Tiêu đề Tùy chọn</h2>
542
543<p>Trong vài trường hợp hiếm gặp, bạn có thể muốn thiết kế các thiết đặt của mình sao cho màn hình thứ nhất
544chỉ hiển thị một danh sách <a href="#Subscreens">các màn hình con</a> (chẳng hạn như trong ứng dụng Thiết đặt của hệ thống,
545như minh họa trong các hình 4 và 5). Khi phát triển thiết kế như vậy cho phiên bản Android 3.0 trở lên, bạn
546nên sử dụng tính năng "tiêu đề" mới trong Android 3.0, thay vì xây dựng màn hình con với các phần tử
547{@link android.preference.PreferenceScreen} lồng nhau.</p>
548
549<p>Để xây dựng thiết đặt có tiêu đề của mình, bạn cần:</p>
550<ol>
551  <li>Tách riêng từng nhóm thiết đặt thành các thực thể riêng của {@link
552android.preference.PreferenceFragment}. Cụ thể, mỗi nhóm thiết đặt cần một tệp XML
553riêng.</li>
554  <li>Tạo một tệp tiêu đề XML liệt kê từng nhóm thiết đặt và khai báo phân đoạn nào
555chứa danh sách thiết đặt tương ứng.</li>
556  <li>Mở rộng lớp {@link android.preference.PreferenceActivity} để lưu trữ các thiết đặt của bạn.</li>
557  <li>Triển khai lệnh gọi lại {@link
558android.preference.PreferenceActivity#onBuildHeaders onBuildHeaders()} để quy định
559tệp tiêu đề.</li>
560</ol>
561
562<p>Một lợi ích tuyệt vời đối với việc sử dụng thiết kế này đó là {@link android.preference.PreferenceActivity}
563tự động trình bày bố trí hai bảng như minh họa trong hình 4 khi chạy trên màn hình lớn.</p>
564
565<p>Ngay cả khi ứng dụng của bạn hỗ trợ các phiên bản Android cũ hơn 3.0, bạn có thể xây dựng ứng dụng
566của mình để sử dụng {@link android.preference.PreferenceFragment} cho một trình chiếu hai bảng trên
567các thiết bị mới hơn, trong khi vẫn hỗ trợ phân cấp đa màn hình truyền thống trên các thiết bị
568cũ hơn (xem phần nói về <a href="#BackCompatHeaders">Hỗ trợ các phiên bản cũ hơn
569với tiêu đề tùy chọn</a>).</p>
570
571<img src="{@docRoot}images/ui/settings/settings-headers-tablet.png" alt="" />
572<p class="img-caption"><strong>Hình 4.</strong> Bố trí có hai bảng với tiêu đề. <br/><b>1.</b>
573Tiêu đề được định nghĩa trong một tệp tiêu đề XML. <br/><b>2.</b> Mỗi nhóm thiết đặt được định nghĩa bởi một
574{@link android.preference.PreferenceFragment}, được quy định bởi một phần tử {@code &lt;header&gt;} trong tệp tiêu đề
575.</p>
576
577<img src="{@docRoot}images/ui/settings/settings-headers-handset.png" alt="" />
578<p class="img-caption"><strong>Hình 5.</strong> Thiết bị cầm tay với các tiêu đề thiết đặt. Khi một
579mục được chọn, {@link android.preference.PreferenceFragment} được liên kết sẽ thay thế
580tiêu đề.</p>
581
582
583<h3 id="CreateHeaders" style="clear:left">Tạo tệp tiêu đề</h3>
584
585<p>Mỗi nhóm thiết đặt trong danh sách tiêu đề của bạn được quy định bởi một phần tử {@code &lt;header&gt;}
586đơn lẻ bên trong một phần tử {@code &lt;preference-headers&gt;} gốc. Ví dụ:</p>
587
588<pre>
589&lt;?xml version="1.0" encoding="utf-8"?>
590&lt;preference-headers xmlns:android="http://schemas.android.com/apk/res/android">
591    &lt;header
592        android:fragment="com.example.prefs.SettingsActivity$SettingsFragmentOne"
593        android:title="@string/prefs_category_one"
594        android:summary="@string/prefs_summ_category_one" />
595    &lt;header
596        android:fragment="com.example.prefs.SettingsActivity$SettingsFragmentTwo"
597        android:title="@string/prefs_category_two"
598        android:summary="@string/prefs_summ_category_two" >
599        &lt;!-- key/value pairs can be included as arguments for the fragment. -->
600        &lt;extra android:name="someKey" android:value="someHeaderValue" />
601    &lt;/header>
602&lt;/preference-headers>
603</pre>
604
605<p>Với thuộc tính {@code android:fragment}, mỗi tiêu đề sẽ khai báo một thực thể của {@link
606android.preference.PreferenceFragment} mà sẽ mở khi người dùng chọn tiêu đề đó.</p>
607
608<p>Phần tử {@code &lt;extras&gt;} cho phép bạn chuyển các cặp khóa-giá trị sang phân đoạn trong một {@link
609android.os.Bundle}. Phân đoạn có thể truy xuất các tham đối bằng cách gọi {@link
610android.app.Fragment#getArguments()}. Bạn có thể chuyển các tham đối tới phân đoạn vì nhiều
611lý do khác nhau, nhưng một lý do chính đáng đó là để sử dụng lại cùng lớp con của {@link
612android.preference.PreferenceFragment} cho mỗi nhóm và sử dụng tham đối để quy định
613tệp XML tùy chọn nào mà phân đoạn cần tải.</p>
614
615<p>Ví dụ, sau đây là một phân đoạn mà có thể được tái sử dụng cho nhiều nhóm thiết đặt, khi từng
616tiêu đề định nghĩa một tham đối {@code &lt;extra&gt;} với khóa {@code "settings"}:</p>
617
618<pre>
619public static class SettingsFragment extends PreferenceFragment {
620    &#64;Override
621    public void onCreate(Bundle savedInstanceState) {
622        super.onCreate(savedInstanceState);
623
624        String settings = getArguments().getString("settings");
625        if ("notifications".equals(settings)) {
626            addPreferencesFromResource(R.xml.settings_wifi);
627        } else if ("sync".equals(settings)) {
628            addPreferencesFromResource(R.xml.settings_sync);
629        }
630    }
631}
632</pre>
633
634
635
636<h3 id="DisplayHeaders">Hiển thị tiêu đề</h3>
637
638<p>Để hiển thị tiêu đề tùy chọn, bạn phải triển khai phương pháp gọi lại {@link
639android.preference.PreferenceActivity#onBuildHeaders onBuildHeaders()} và gọi
640{@link android.preference.PreferenceActivity#loadHeadersFromResource
641loadHeadersFromResource()}. Ví dụ:</p>
642
643<pre>
644public class SettingsActivity extends PreferenceActivity {
645    &#64;Override
646    public void onBuildHeaders(List&lt;Header> target) {
647        loadHeadersFromResource(R.xml.preference_headers, target);
648    }
649}
650</pre>
651
652<p>Khi người dùng chọn một mục từ danh sách tiêu đề, hệ thống sẽ mở {@link
653android.preference.PreferenceFragment} kèm theo.</p>
654
655<p class="note"><strong>Lưu ý:</strong> Khi sử dụng tiêu đề tùy chọn, lớp con {@link
656android.preference.PreferenceActivity} của bạn không cần triển khai phương pháp {@link
657android.preference.PreferenceActivity#onCreate onCreate()}, vì tác vụ cần thiết duy nhất
658cho hoạt động đó là tải tiêu đề.</p>
659
660
661<h3 id="BackCompatHeaders">Hỗ trợ các phiên bản cũ hơn với tiêu đề tùy chọn</h3>
662
663<p>Nếu ứng dụng của bạn hỗ trợ các phiên bản Android cũ hơn 3.0, bạn vẫn có thể sử dụng tiêu đề để
664cung cấp một bố trí hai bảng khi chạy trên Android 3.0 trở lên. Tất cả những việc bạn cần làm đó là tạo một
665tệp XML tùy chọn bổ sung có sử dụng phần tử cơ bản {@link android.preference.Preference
666&lt;Preference&gt;} đóng vai trò như mục tiêu đề (để dùng cho các phiên bản Android
667cũ hơn).</p>
668
669<p>Tuy nhiên, thay vì mở một {@link android.preference.PreferenceScreen} mới, từng phần tử {@link
670android.preference.Preference &lt;Preference&gt;} sẽ gửi một {@link android.content.Intent} tới
671{@link android.preference.PreferenceActivity} mà quy định tệp XML tùy chọn cần
672tải.</p>
673
674<p>Ví dụ, sau đây là một tệp XML cho các tiêu đề tùy chọn được sử dụng trên Android 3.0
675trở lên ({@code res/xml/preference_headers.xml}):</p>
676
677<pre>
678&lt;preference-headers xmlns:android="http://schemas.android.com/apk/res/android">
679    &lt;header
680        android:fragment="com.example.prefs.SettingsFragmentOne"
681        android:title="@string/prefs_category_one"
682        android:summary="@string/prefs_summ_category_one" />
683    &lt;header
684        android:fragment="com.example.prefs.SettingsFragmentTwo"
685        android:title="@string/prefs_category_two"
686        android:summary="@string/prefs_summ_category_two" />
687&lt;/preference-headers>
688</pre>
689
690<p>Và sau đây là một tệp tùy chọn cung cấp cùng các tiêu đề cho các phiên bản cũ hơn
691Android 3.0 ({@code res/xml/preference_headers_legacy.xml}):</p>
692
693<pre>
694&lt;PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
695    &lt;Preference
696        android:title="@string/prefs_category_one"
697        android:summary="@string/prefs_summ_category_one"  >
698        &lt;intent
699            android:targetPackage="com.example.prefs"
700            android:targetClass="com.example.prefs.SettingsActivity"
701            android:action="com.example.prefs.PREFS_ONE" />
702    &lt;/Preference>
703    &lt;Preference
704        android:title="@string/prefs_category_two"
705        android:summary="@string/prefs_summ_category_two" >
706        &lt;intent
707            android:targetPackage="com.example.prefs"
708            android:targetClass="com.example.prefs.SettingsActivity"
709            android:action="com.example.prefs.PREFS_TWO" />
710    &lt;/Preference>
711&lt;/PreferenceScreen>
712</pre>
713
714<p>Vì hỗ trợ dành cho {@code &lt;preference-headers&gt;} đã được thêm trong Android 3.0, hệ thống sẽ gọi
715{@link android.preference.PreferenceActivity#onBuildHeaders onBuildHeaders()} trong {@link
716android.preference.PreferenceActivity} của bạn chỉ khi đang chạy trên phiên bản Androd 3.0 hoặc cao hơn. Để tải
717tệp tiêu đề "kế thừa" ({@code preference_headers_legacy.xml}), bạn phải kiểm tra phiên bản Android
718và, nếu phiên bản cũ hơn Android 3.0 ({@link
719android.os.Build.VERSION_CODES#HONEYCOMB}), hãy gọi {@link
720android.preference.PreferenceActivity#addPreferencesFromResource addPreferencesFromResource()} để
721tải tệp tiêu đề kế thừa. Ví dụ:</p>
722
723<pre>
724&#64;Override
725public void onCreate(Bundle savedInstanceState) {
726    super.onCreate(savedInstanceState);
727    ...
728
729    if (Build.VERSION.SDK_INT &lt; Build.VERSION_CODES.HONEYCOMB) {
730        // Load the legacy preferences headers
731        addPreferencesFromResource(R.xml.preference_headers_legacy);
732    }
733}
734
735// Called only on Honeycomb and later
736&#64;Override
737public void onBuildHeaders(List&lt;Header> target) {
738   loadHeadersFromResource(R.xml.preference_headers, target);
739}
740</pre>
741
742<p>Việc duy nhất còn lại cần làm đó là xử lý {@link android.content.Intent} mà được chuyển vào
743hoạt động để nhận biết tệp tùy chọn nào cần tải. Vì vậy, hãy truy xuất hành động của ý định và so sánh nó với
744các xâu hành động đã biết mà bạn đã sử dụng trong tag {@code &lt;intent&gt;} của XML tùy chọn:</p>
745
746<pre>
747final static String ACTION_PREFS_ONE = "com.example.prefs.PREFS_ONE";
748...
749
750&#64;Override
751public void onCreate(Bundle savedInstanceState) {
752    super.onCreate(savedInstanceState);
753
754    String action = getIntent().getAction();
755    if (action != null &amp;&amp; action.equals(ACTION_PREFS_ONE)) {
756        addPreferencesFromResource(R.xml.preferences);
757    }
758    ...
759
760    else if (Build.VERSION.SDK_INT &lt; Build.VERSION_CODES.HONEYCOMB) {
761        // Load the legacy preferences headers
762        addPreferencesFromResource(R.xml.preference_headers_legacy);
763    }
764}
765</pre>
766
767<p>Lưu ý rằng các lệnh gọi liên tiếp đến {@link
768android.preference.PreferenceActivity#addPreferencesFromResource addPreferencesFromResource()} sẽ
769xếp chồng tất cả tùy chọn trong một danh sách duy nhất, vì thế hãy chắc chắn rằng nó chỉ được gọi một lần bằng cách liên kết các
770điều kiện với mệnh đề else-if.</p>
771
772
773
774
775
776<h2 id="ReadingPrefs">Đọc Tùy chọn</h2>
777
778<p>Theo mặc định, tất cả tùy chọn của ứng dụng của bạn đều được lưu vào một tệp có thể truy cập từ bất kỳ nơi nào
779trong ứng dụng của bạn bằng cách gọi phương pháp tĩnh {@link
780android.preference.PreferenceManager#getDefaultSharedPreferences
781PreferenceManager.getDefaultSharedPreferences()}. Điều này sẽ trả về đối tượng {@link
782android.content.SharedPreferences} chứa tất cả cặp khóa-giá trị liên kết
783với các đối tượng {@link android.preference.Preference} được sử dụng trong {@link
784android.preference.PreferenceActivity}.</p>
785
786<p>Ví dụ, sau đây là cách bạn có thể đọc một trong các giá trị tùy chọn từ bất kỳ hoạt động nào khác trong ứng dụng
787của mình:</p>
788
789<pre>
790SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
791String syncConnPref = sharedPref.getString(SettingsActivity.KEY_PREF_SYNC_CONN, "");
792</pre>
793
794
795
796<h3 id="Listening">Theo dõi thay đổi tùy chọn</h3>
797
798<p>Có một vài lý do khiến bạn có thể muốn được thông báo càng sớm càng tốt nếu người dùng thay đổi một trong các
799tùy chọn. Để nhận một phương pháp gọi lại khi thay đổi xảy ra với bất kỳ tùy chọn nào,
800hãy triển khai giao diện {@link android.content.SharedPreferences.OnSharedPreferenceChangeListener
801SharedPreference.OnSharedPreferenceChangeListener} và đăng ký đối tượng theo dõi cho đối tượng
802{@link android.content.SharedPreferences} bằng cách gọi {@link
803android.content.SharedPreferences#registerOnSharedPreferenceChangeListener
804registerOnSharedPreferenceChangeListener()}.</p>
805
806<p>Giao diện này chỉ có một phương pháp gọi lại, {@link
807android.content.SharedPreferences.OnSharedPreferenceChangeListener#onSharedPreferenceChanged
808onSharedPreferenceChanged()}, và bạn có thể thấy đây là cách dễ nhất để triển khai giao diện như một phần
809hoạt động của mình. Ví dụ:</p>
810
811<pre>
812public class SettingsActivity extends PreferenceActivity
813                              implements OnSharedPreferenceChangeListener {
814    public static final String KEY_PREF_SYNC_CONN = "pref_syncConnectionType";
815    ...
816
817    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
818        String key) {
819        if (key.equals(KEY_PREF_SYNC_CONN)) {
820            Preference connectionPref = findPreference(key);
821            // Set summary to be the user-description for the selected value
822            connectionPref.setSummary(sharedPreferences.getString(key, ""));
823        }
824    }
825}
826</pre>
827
828<p>Trong ví dụ này, phương pháp sẽ kiểm tra xem thiết đặt bị thay đổi có áp dụng cho một khóa tùy chọn đã biết không. Nó
829sẽ gọi {@link android.preference.PreferenceActivity#findPreference findPreference()} để nhận đối tượng
830{@link android.preference.Preference} đã bị thay đổi để nó có thể sửa đổi tóm tắt
831của mục đó thành mô tả lựa chọn của người dùng. Cụ thể, khi thiết đặt là một {@link
832android.preference.ListPreference} hoặc thiết đặt nhiều lựa chọn khác, bạn nên gọi {@link
833android.preference.Preference#setSummary setSummary()} khi thiết đặt thay đổi để hiển thị
834trạng thái hiện tại (chẳng hạn như thiết đặt Ngủ như minh họa trong hình 5).</p>
835
836<p class="note"><strong>Lưu ý:</strong> Như đã mô tả trong tài liệu Thiết kế Android về <a href="{@docRoot}design/patterns/settings.html">Thiết đặt</a>, chúng tôi khuyên bạn nên cập nhật
837tóm tắt cho {@link android.preference.ListPreference} mỗi khi người dùng thay đổi tùy chọn để
838mô tả thiết đặt hiện tại.</p>
839
840<p>Để quản lý vòng đời trong hoạt động cho phù hợp, chúng tôi khuyên rằng bạn nên đăng ký và bỏ đăng ký
841{@link android.content.SharedPreferences.OnSharedPreferenceChangeListener} của mình tương ứng trong {@link
842android.app.Activity#onResume} và các lệnh gọi lại {@link android.app.Activity#onPause}:</p>
843
844<pre>
845&#64;Override
846protected void onResume() {
847    super.onResume();
848    getPreferenceScreen().getSharedPreferences()
849            .registerOnSharedPreferenceChangeListener(this);
850}
851
852&#64;Override
853protected void onPause() {
854    super.onPause();
855    getPreferenceScreen().getSharedPreferences()
856            .unregisterOnSharedPreferenceChangeListener(this);
857}
858</pre>
859
860<p class="caution"><strong>Chú ý:</strong> Khi bạn gọi {@link
861android.content.SharedPreferences#registerOnSharedPreferenceChangeListener
862registerOnSharedPreferenceChangeListener()}, trình quản lý tùy chọn hiện
863không lưu trữ một tham chiếu mạnh tới đối tượng theo dõi. Bạn phải lưu trữ một tham chiếu
864mạnh tới đối tượng theo dõi, nếu không nó sẽ dễ bị thu thập thông tin rác. Chúng tôi
865khuyên bạn nên giữ một tham chiếu tới đối tượng theo dõi trong dữ liệu thực thể của một đối tượng
866mà sẽ tồn tại miễn là bạn còn cần đối tượng theo dõi đó.</p>
867
868<p>Ví dụ, trong đoạn mã sau, hàm gọi không giữ tham chiếu tới
869đối tượng theo dõi. Kết quả là đối tượng theo dõi sẽ bị thu thập thông tin rác,
870và nó sẽ bị lỗi tại một thời điểm không xác định trong tương lai:</p>
871
872<pre>
873prefs.registerOnSharedPreferenceChangeListener(
874  // Bad! The listener is subject to garbage collection!
875  new SharedPreferences.OnSharedPreferenceChangeListener() {
876  public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
877    // listener implementation
878  }
879});
880</pre>
881
882<p>Thay vào đó, hãy lưu một tham chiếu tới đối tượng theo dõi trong một trường dữ liệu thực thể của một
883đối tượng mà sẽ tồn tại miễn là còn cần đối tượng theo dõi đó:</p>
884
885<pre>
886SharedPreferences.OnSharedPreferenceChangeListener listener =
887    new SharedPreferences.OnSharedPreferenceChangeListener() {
888  public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
889    // listener implementation
890  }
891};
892prefs.registerOnSharedPreferenceChangeListener(listener);
893</pre>
894
895<h2 id="NetworkUsage">Quản lý Sử dụng Mạng</h2>
896
897
898<p>Bắt đầu với Android 4.0, ứng dụng Thiết đặt của hệ thống sẽ cho phép người dùng xem
899ứng dụng của họ đang sử dụng bao nhiêu dữ liệu mạng khi đang ở tiền cảnh và dưới nền. Khi đó, người dùng có thể
900vô hiệu hóa việc sử dụng dữ liệu chạy ngầm cho từng ứng dụng. Để tránh việc người dùng vô hiệu hóa truy cập dữ liệu
901của ứng dụng của bạn từ dưới nền, bạn nên sử dụng kết nối dữ liệu một cách hiệu quả và cho phép
902người dùng tinh chỉnh mức sử dụng dữ liệu cho ứng dụng của bạn thông qua thiết đặt ứng dụng.<p>
903
904<p>Ví dụ, bạn có thể cho phép người dùng kiểm soát tần suất ứng dụng của bạn đồng bộ dữ liệu, ứng dụng của bạn
905chỉ được thực hiện tải lên/tải xuống khi trên Wi-Fi, ứng dụng của bạn sử dụng dữ liệu trong khi đang chuyển vùng dữ liệu, v.v... hay không. Với
906những kiểm soát này, người dùng sẽ ít có khả năng vô hiệu hóa truy cập dữ liệu của ứng dụng của bạn
907hơn nhiều khi họ đạt gần mức giới hạn đặt ra trong Thiết đặt hệ thống, vì thay vào đó, họ có thể kiểm soát chính xác
908lượng dữ liệu mà ứng dụng của bạn sử dụng.</p>
909
910<p>Sau khi bạn đã thêm các tùy chọn cần thiết trong {@link android.preference.PreferenceActivity}
911của mình để kiểm soát các thói quen dữ liệu của ứng dụng của bạn, bạn nên thêm một bộ lọc ý định cho {@link
912android.content.Intent#ACTION_MANAGE_NETWORK_USAGE} trong tệp bản kê khai của mình. Ví dụ:</p>
913
914<pre>
915&lt;activity android:name="SettingsActivity" ... >
916    &lt;intent-filter>
917       &lt;action android:name="android.intent.action.MANAGE_NETWORK_USAGE" />
918       &lt;category android:name="android.intent.category.DEFAULT" />
919    &lt;/intent-filter>
920&lt;/activity>
921</pre>
922
923<p>Bộ lọc ý định này cho hệ thống biết rằng đây là hoạt động kiểm soát mức sử dụng dữ liệu
924của ứng dụng của bạn. Vì thế, khi người dùng kiểm tra lượng dữ liệu mà ứng dụng của bạn đang dùng từ ứng dụng
925Thiết đặt của hệ thống, sẽ có một nút <em>Xem thiết đặt ứng dụng</em> khởi chạy
926{@link android.preference.PreferenceActivity} của bạn, vì thế người dùng có thể tinh chỉnh lượng dữ liệu mà ứng dụng của bạn
927dùng.</p>
928
929
930
931
932
933
934
935<h2 id="Custom">Xây dựng một Thiết đặt Tùy chỉnh</h2>
936
937<p>Khuôn khổ Android bao gồm nhiều lớp con {@link android.preference.Preference} mà
938cho phép bạn xây dựng một UI cho một vài loại thiết đặt khác nhau.
939Tuy nhiên, bạn có thể khám phá thiết đặt mình cần mà chưa có giải pháp tích hợp sẵn, chẳng hạn như một
940bộ chọn số hay bộ chọn ngày. Trong trường hợp như vậy, bạn sẽ cần tạo một tùy chọn tùy chỉnh bằng cách mở rộng
941lớp {@link android.preference.Preference} hoặc một trong các lớp con khác.</p>
942
943<p>Khi bạn mở rộng lớp {@link android.preference.Preference}, có một vài điều quan trọng
944mà bạn cần làm:</p>
945
946<ul>
947  <li>Quy định giao diện người dùng sẽ xuất hiện khi người dùng chọn thiết đặt.</li>
948  <li>Lưu giá trị của thiết đặt khi phù hợp.</li>
949  <li>Khởi tạo {@link android.preference.Preference} bằng giá trị hiện tại (hoặc mặc định)
950khi xét tới dạng xem.</li>
951  <li>Cung cấp giá trị mặc định khi hệ thống yêu cầu.</li>
952  <li>Nếu {@link android.preference.Preference} cung cấp UI của chính mình (chẳng hạn như một hộp thoại), hãy lưu
953và khôi phục trạng thái để xử lý các thay đổi trong vòng đời (chẳng hạn như khi người dùng xoay màn hình).</li>
954</ul>
955
956<p>Các phần sau mô tả cách hoàn thành từng tác vụ này.</p>
957
958
959
960<h3 id="CustomSelected">Quy định một giao diện người dùng</h3>
961
962  <p>Nếu bạn trực tiếp mở rộng lớp {@link android.preference.Preference}, bạn cần triển khai
963{@link android.preference.Preference#onClick()} để định nghĩa hành động xảy ra khi người dùng
964chọn mục. Tuy nhiên, hầu hết các thiết đặt tùy chỉnh sẽ mở rộng {@link android.preference.DialogPreference} để
965hiển thị một hộp thoại, điều này làm đơn giản hóa quy trình. Khi bạn mở rộng {@link
966android.preference.DialogPreference}, bạn phải gọi {@link
967android.preference.DialogPreference#setDialogLayoutResource setDialogLayoutResourcs()} trong khi đang ở trong
968hàm dựng lớp để quy định bố trí cho hộp thoại.</p>
969
970  <p>Ví dụ, sau đây là hàm dựng cho một {@link
971android.preference.DialogPreference} tùy chỉnh mà khai báo bố trí và quy định văn bản cho
972các nút hộp thoại tích cực và tiêu cực mặc định:</p>
973
974<pre>
975public class NumberPickerPreference extends DialogPreference {
976    public NumberPickerPreference(Context context, AttributeSet attrs) {
977        super(context, attrs);
978
979        setDialogLayoutResource(R.layout.numberpicker_dialog);
980        setPositiveButtonText(android.R.string.ok);
981        setNegativeButtonText(android.R.string.cancel);
982
983        setDialogIcon(null);
984    }
985    ...
986}
987</pre>
988
989
990
991<h3 id="CustomSave">Lưu giá trị của thiết đặt</h3>
992
993<p>Bạn có thể lưu một giá trị cho thiết đặt vào bất cứ lúc nào bằng cách gọi một trong các phương pháp của lớp {@link
994android.preference.Preference}, {@code persist*()}, chẳng hạn như {@link
995android.preference.Preference#persistInt persistInt()} nếu giá trị của thiết đặt là một số nguyên hoặc
996{@link android.preference.Preference#persistBoolean persistBoolean()} để lưu một boolean.</p>
997
998<p class="note"><strong>Lưu ý:</strong> Mỗi {@link android.preference.Preference} chỉ có thể lưu một
999kiểu dữ liệu, vì thế bạn phải sử dụng phương pháp {@code persist*()} phù hợp cho kiểu dữ liệu được sử dụng bởi
1000{@link android.preference.Preference} tùy chỉnh của mình.</p>
1001
1002<p>Thời điểm bạn chọn duy trì thiết đặt có thể phụ thuộc vào lớp {@link
1003android.preference.Preference} nào mà bạn mở rộng. Nếu mở rộng {@link
1004android.preference.DialogPreference}, khi đó bạn nên duy trì giá trị đó chỉ khi hộp thoại
1005đóng lại do kết quả tích cực (người dùng chọn nút "OK").</p>
1006
1007<p>Khi {@link android.preference.DialogPreference} đóng lại, hệ thống sẽ gọi phương pháp {@link
1008android.preference.DialogPreference#onDialogClosed onDialogClosed()}. Phương pháp bao gồm một
1009tham đối boolean quy định xem người dùng có trả về kết quả "tích cực" hay không&mdash;nếu kết quả là
1010<code>true</code>, khi đó, người dùng đã chọn nút tích cực và bạn nên lưu giá trị mới này. Ví
1011dụ:</p>
1012
1013<pre>
1014&#64;Override
1015protected void onDialogClosed(boolean positiveResult) {
1016    // When the user selects "OK", persist the new value
1017    if (positiveResult) {
1018        persistInt(mNewValue);
1019    }
1020}
1021</pre>
1022
1023<p>Trong ví dụ này, <code>mNewValue</code> là một thành viên lớp lưu giữ giá trị
1024hiện tại của thiết đặt. Việc gọi {@link android.preference.Preference#persistInt persistInt()} sẽ lưu giá trị vào
1025tệp {@link android.content.SharedPreferences} (tự động sử dụng khóa mà
1026được quy định trong tệp XML cho {@link android.preference.Preference} này).</p>
1027
1028
1029<h3 id="CustomInitialize">Khởi tạo giá trị hiện tại</h3>
1030
1031<p>Khi hệ thống thêm {@link android.preference.Preference} của bạn vào màn hình, nó
1032gọi {@link android.preference.Preference#onSetInitialValue onSetInitialValue()} để thông báo
1033với bạn xem thiết đặt có giá trị được duy trì hay không. Nếu không có giá trị được duy trì, lệnh gọi này sẽ cung cấp
1034cho bạn giá trị mặc định.</p>
1035
1036<p>Phương pháp {@link android.preference.Preference#onSetInitialValue onSetInitialValue()} chuyển một
1037boolean, <code>restorePersistedValue</code>, để cho biết liệu giá trị đã được duy trì
1038cho thiết đặt hay không. Nếu nó là <code>true</code>, khi đó bạn nên truy xuất giá trị được duy trì bằng cách gọi
1039một trong các phương pháp của lớp {@link
1040android.preference.Preference}, {@code getPersisted*()}, chẳng hạn như {@link
1041android.preference.Preference#getPersistedInt getPersistedInt()} đối với một giá trị số nguyên. Bạn sẽ
1042thường muốn truy xuất giá trị được duy trì sao cho bạn có thể cập nhật UI cho phù hợp để phản ánh
1043giá trị đã lưu trước đó.</p>
1044
1045<p>Nếu <code>restorePersistedValue</code> là <code>false</code>, vậy bạn
1046nên sử dụng giá trị mặc định được chuyển trong tham đối thứ hai.</p>
1047
1048<pre>
1049&#64;Override
1050protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue) {
1051    if (restorePersistedValue) {
1052        // Restore existing state
1053        mCurrentValue = this.getPersistedInt(DEFAULT_VALUE);
1054    } else {
1055        // Set default state from the XML attribute
1056        mCurrentValue = (Integer) defaultValue;
1057        persistInt(mCurrentValue);
1058    }
1059}
1060</pre>
1061
1062<p>Mỗi phương pháp {@code getPersisted*()} sẽ lấy một tham đối quy định
1063giá trị mặc định sẽ sử dụng trong trường hợp thực sự không có giá trị được duy trì hoặc khóa không tồn tại. Trong
1064ví dụ trên, một hằng số cục bộ được sử dụng để quy định giá trị mặc định trong trường hợp {@link
1065android.preference.Preference#getPersistedInt getPersistedInt()} không thể trả về một giá trị được duy trì.</p>
1066
1067<p class="caution"><strong>Chú ý:</strong> Bạn <strong>không thể</strong> sử dụng
1068<code>defaultValue</code> làm giá trị mặc định trong phương pháp {@code getPersisted*()}, bởi
1069giá trị của nó luôn rỗng khi <code>restorePersistedValue</code> là <code>true</code>.</p>
1070
1071
1072<h3 id="CustomDefault">Cung cấp một giá trị mặc định</h3>
1073
1074<p>Nếu trường hợp lớp {@link android.preference.Preference} của bạn quy định một giá trị mặc định
1075(với thuộc tính {@code android:defaultValue}), khi đó hệ thống
1076sẽ gọi {@link android.preference.Preference#onGetDefaultValue
1077onGetDefaultValue()} khi nó khởi tạo đối tượng để truy xuất giá trị. Bạn phải
1078triển khai phương pháp này để hệ thống lưu giá trị mặc định trong {@link
1079android.content.SharedPreferences}. Ví dụ:</p>
1080
1081<pre>
1082&#64;Override
1083protected Object onGetDefaultValue(TypedArray a, int index) {
1084    return a.getInteger(index, DEFAULT_VALUE);
1085}
1086</pre>
1087
1088<p>Các tham đối của phương pháp cung cấp mọi thứ bạn cần: mảng thuộc tính và vị trí chỉ mục
1089của {@code android:defaultValue} mà bạn phải truy xuất. Lý do bạn phải triển khai
1090phương pháp này nhằm trích xuất giá trị mặc định từ thuộc tính đó là bởi bạn phải quy định
1091một giá trị mặc định cục bộ cho thuộc tính trong trường hợp giá trị không được định nghĩa.</p>
1092
1093
1094
1095<h3 id="CustomSaveState">Lưu và khôi phục trạng thái của Tùy chọn</h3>
1096
1097<p>Giống như {@link android.view.View} trong một bố trí, lớp con {@link android.preference.Preference}
1098của bạn chịu trách nhiệm lưu và khôi phục trạng thái của nó trong trường hợp hoạt động hoặc phân đoạn
1099được khởi động lại (chẳng hạn như khi người dùng xoay màn hình). Để lưu và khôi phục
1100trạng thái của lớp {@link android.preference.Preference} của bạn cho đúng, bạn phải triển khai các
1101phương pháp gọi lại vòng đời {@link android.preference.Preference#onSaveInstanceState
1102onSaveInstanceState()} và {@link
1103android.preference.Preference#onRestoreInstanceState onRestoreInstanceState()}.</p>
1104
1105<p>Trạng thái của {@link android.preference.Preference} của bạn được định nghĩa bởi một đối tượng mà triển khai
1106giao diện {@link android.os.Parcelable}. Khuôn khổ Android sẽ cung cấp một đối tượng như vậy cho bạn
1107như một điểm bắt đầu để định nghĩa đối tượng trạng thái của bạn: lớp {@link
1108android.preference.Preference.BaseSavedState}.</p>
1109
1110<p>Để định nghĩa cách thức lớp {@link android.preference.Preference} của bạn lưu trạng thái của nó
1111hãy mở rộng lớp {@link android.preference.Preference.BaseSavedState}. Bạn cần khống chế chỉ
1112 một vài phương pháp và định nghĩa đối tượng {@link android.preference.Preference.BaseSavedState#CREATOR}
1113.</p>
1114
1115<p>Đối với hầu hết ứng dụng, bạn có thể sao chép triển khai sau và chỉ cần thay đổi các dòng
1116xử lý {@code value} nếu lớp con {@link android.preference.Preference} của bạn lưu một kiểu
1117dữ liệu khác số nguyên.</p>
1118
1119<pre>
1120private static class SavedState extends BaseSavedState {
1121    // Member that holds the setting's value
1122    // Change this data type to match the type saved by your Preference
1123    int value;
1124
1125    public SavedState(Parcelable superState) {
1126        super(superState);
1127    }
1128
1129    public SavedState(Parcel source) {
1130        super(source);
1131        // Get the current preference's value
1132        value = source.readInt();  // Change this to read the appropriate data type
1133    }
1134
1135    &#64;Override
1136    public void writeToParcel(Parcel dest, int flags) {
1137        super.writeToParcel(dest, flags);
1138        // Write the preference's value
1139        dest.writeInt(value);  // Change this to write the appropriate data type
1140    }
1141
1142    // Standard creator object using an instance of this class
1143    public static final Parcelable.Creator&lt;SavedState> CREATOR =
1144            new Parcelable.Creator&lt;SavedState>() {
1145
1146        public SavedState createFromParcel(Parcel in) {
1147            return new SavedState(in);
1148        }
1149
1150        public SavedState[] newArray(int size) {
1151            return new SavedState[size];
1152        }
1153    };
1154}
1155</pre>
1156
1157<p>Với triển khai {@link android.preference.Preference.BaseSavedState} bên trên được thêm
1158vào ứng dụng của bạn (thường dưới dạng một lớp con của lớp con {@link android.preference.Preference} của bạn), khi đó
1159bạn cần triển khai các phương pháp {@link android.preference.Preference#onSaveInstanceState
1160onSaveInstanceState()} và {@link
1161android.preference.Preference#onRestoreInstanceState onRestoreInstanceState()} cho lớp con
1162{@link android.preference.Preference} của mình.</p>
1163
1164<p>Ví dụ:</p>
1165
1166<pre>
1167&#64;Override
1168protected Parcelable onSaveInstanceState() {
1169    final Parcelable superState = super.onSaveInstanceState();
1170    // Check whether this Preference is persistent (continually saved)
1171    if (isPersistent()) {
1172        // No need to save instance state since it's persistent,
1173        // use superclass state
1174        return superState;
1175    }
1176
1177    // Create instance of custom BaseSavedState
1178    final SavedState myState = new SavedState(superState);
1179    // Set the state's value with the class member that holds current
1180    // setting value
1181    myState.value = mNewValue;
1182    return myState;
1183}
1184
1185&#64;Override
1186protected void onRestoreInstanceState(Parcelable state) {
1187    // Check whether we saved the state in onSaveInstanceState
1188    if (state == null || !state.getClass().equals(SavedState.class)) {
1189        // Didn't save the state, so call superclass
1190        super.onRestoreInstanceState(state);
1191        return;
1192    }
1193
1194    // Cast state to custom BaseSavedState and pass to superclass
1195    SavedState myState = (SavedState) state;
1196    super.onRestoreInstanceState(myState.getSuperState());
1197
1198    // Set this Preference's widget to reflect the restored state
1199    mNumberPicker.setValue(myState.value);
1200}
1201</pre>
1202
1203