Kiến trúc thông tin

Android 8.0 đã giới thiệu một cấu trúc thông tin mới cho ứng dụng Cài đặt nhằm đơn giản hoá cách sắp xếp các chế độ cài đặt và giúp người dùng nhanh chóng tìm thấy các chế độ cài đặt để tuỳ chỉnh thiết bị Android. Android 9 đã giới thiệu một số điểm cải tiến để cung cấp thêm nhiều chức năng Cài đặt và triển khai dễ dàng hơn.

Ví dụ và nguồn

Hầu hết các trang trong phần Cài đặt hiện được triển khai bằng khung mới. Một ví dụ điển hình là DisplaySettings: packages/apps/Settings/src/com/android/settings/DisplaySettings.java

Dưới đây là danh sách đường dẫn tệp cho các thành phần quan trọng:

  • CategoryKey: packages/SettingsLib/src/com/android/settingslib/drawer/CategoryKey.java
  • dashboardFragmentRegistry: packages/apps/Settings/src/com/android/settings/dashboard/DashboardFragmentRegistry.java
  • Bảng điều khiển: packages/apps/Settings/src/com/android/settings/dashboard/DashboardFragment.java
  • AbstractPreferenceController: frameworks/base/packages/SettingsLib/src/com/android/settingslib/core/AbstractPreferenceController.java
  • BasePreferenceController (được giới thiệu trong Android 9): packages/apps/Settings/src/com/android/settings/core/BasePreferenceController.java

Triển khai

Nhà sản xuất thiết bị nên điều chỉnh cấu trúc thông tin Cài đặt hiện có và chèn thêm các trang cài đặt bổ sung nếu cần cho phù hợp với các tính năng dành riêng cho đối tác. Việc di chuyển các lựa chọn ưu tiên từ trang cũ (triển khai dưới dạng SettingsPreferencePage) sang một trang mới (triển khai bằng DashboardFragment) có thể phức tạp. Có thể bạn sẽ không triển khai lựa chọn ưu tiên trên trang cũ bằng PreferenceController.

Vì vậy, khi di chuyển một lựa chọn ưu tiên từ một trang cũ sang một trang mới, bạn cần tạo PreferenceController và di chuyển mã vào trình điều khiển trước khi tạo thực thể cho mã đó trong DashboardFragment mới. Các API mà PreferenceController yêu cầu được mô tả trong tên và được ghi lại trong Javadoc.

Bạn nên thêm một bài kiểm thử đơn vị cho mỗi PreferenceController. Nếu thay đổi được gửi tới AOSP, thì bạn cần phải kiểm thử đơn vị. Để biết thêm thông tin về cách viết chương trình kiểm thử dựa trên Robolectric, hãy xem tệp readme packages/apps/Settings/tests/robotests/README.md.

Cấu trúc thông tin kiểu trình bổ trợ

Mỗi mục cài đặt được triển khai dưới dạng Lựa chọn ưu tiên. Bạn có thể dễ dàng di chuyển Lựa chọn ưu tiên từ trang này sang trang khác.

Để giúp di chuyển nhiều chế độ cài đặt dễ dàng hơn, Android 8.0 đã giới thiệu một mảnh máy chủ theo kiểu trình bổ trợ chứa các mục cài đặt. Các mục cài đặt được mô hình hoá dưới dạng bộ điều khiển kiểu trình bổ trợ. Do đó, trang cài đặt được xây dựng bởi một mảnh máy chủ lưu trữ và nhiều bộ điều khiển cài đặt.

Mảnh trang tổng quan

DashboardFragment là máy chủ lưu trữ các trình điều khiển lựa chọn ưu tiên kiểu trình bổ trợ. Mảnh kế thừa từ PreferenceFragment và có các hook để mở rộng cũng như cập nhật cả danh sách lựa chọn ưu tiên tĩnh và danh sách lựa chọn ưu tiên động.

Lựa chọn ưu tiên tĩnh

Danh sách lựa chọn ưu tiên tĩnh được xác định trong tệp XML bằng thẻ <Preference>. Cách triển khai DashboardFragment sử dụng phương thức getPreferenceScreenResId() để xác định tệp XML nào chứa danh sách lựa chọn ưu tiên tĩnh cần hiển thị.

Lựa chọn ưu tiên linh động

Một mục động biểu thị một thẻ thông tin có ý định, dẫn đến một Hoạt động bên ngoài hoặc nội bộ. Thông thường, ý định dẫn đến một trang cài đặt khác. Ví dụ: mục cài đặt "Google" trong trang chủ Cài đặt là một mục động. Các mục động được xác định trong AndroidManifest (sẽ thảo luận bên dưới) và được tải thông qua FeatureProvider (được khai báo là DashboardFeatureProvider).

Các chế độ cài đặt động có trọng số lớn hơn so với chế độ cài đặt được định cấu hình tĩnh. Vì vậy, các nhà phát triển thường nên triển khai chế độ cài đặt này dưới dạng chế độ tĩnh. Tuy nhiên, chế độ cài đặt động có thể hữu ích khi bất kỳ trường hợp nào sau đây xảy ra:

  • Chế độ cài đặt này không được triển khai trực tiếp trong ứng dụng Cài đặt (chẳng hạn như chèn một chế độ cài đặt do các ứng dụng OEM/Nhà mạng triển khai).
  • Cài đặt này sẽ xuất hiện trên trang chủ Cài đặt.
  • Bạn đã có Hoạt động cho chế độ cài đặt này và không muốn triển khai cấu hình tĩnh bổ sung.

Để định cấu hình một Hoạt động dưới dạng chế độ cài đặt động, hãy làm như sau:

  • Đánh dấu hoạt động dưới dạng chế độ cài đặt động bằng cách thêm bộ lọc ý định vào hoạt động.
  • Cho ứng dụng Cài đặt biết ứng dụng thuộc danh mục nào. Danh mục là một hằng số, được xác định trong CategoryKey.
  • Không bắt buộc: Thêm văn bản tóm tắt khi chế độ cài đặt hiển thị.

Dưới đây là ví dụ lấy từ ứng dụng Cài đặt cho DisplaySettings.

<activity android:name="Settings$DisplaySettingsActivity"
                   android:label="@string/display_settings"
                   android:icon="@drawable/ic_settings_display">
             <!-- Mark the activity as a dynamic setting -->
              <intent-filter>
                     <action android:name="com.android.settings.action.IA_SETTINGS" />
              </intent-filter>
             <!-- Tell Settings app which category it belongs to -->
              <meta-data android:name="com.android.settings.category"
                     android:value="com.android.settings.category.ia.homepage" />
             <!-- Add a summary text when the setting is displayed -->
              <meta-data android:name="com.android.settings.summary"
                     android:resource="@string/display_dashboard_summary"/>
             </activity>

Tại thời điểm kết xuất, mảnh sẽ yêu cầu danh sách các Lựa chọn ưu tiên trong cả chế độ cài đặt XML tĩnh và chế độ cài đặt động được xác định trong AndroidManifest. Cho dù PreferenceController được xác định trong mã Java hay trong XML, DashboardFragment đều quản lý logic xử lý của từng chế độ cài đặt thông qua PreferenceController (sẽ được thảo luận bên dưới). Sau đó, các sự kiện này sẽ hiển thị trong giao diện người dùng dưới dạng danh sách kết hợp.

PreferenceController

Có sự khác biệt giữa việc triển khai PreferenceController trong Android 9 và Android 8.x, như mô tả trong phần này.

Bản phát hành PreferenceController trong Android 9

PreferenceController chứa mọi logic để tương tác với lựa chọn ưu tiên, bao gồm cả việc hiển thị, cập nhật, lập chỉ mục tìm kiếm, v.v.

Giao diện của PreferenceController được định nghĩa là BasePreferenceController. Ví dụ: xem mã trong packages/apps/Settings/src/com/android/settings/core/ BasePreferenceController.java

BasePreferenceController có một số lớp con, mỗi lớp liên kết đến một kiểu giao diện người dùng cụ thể mà ứng dụng Cài đặt hỗ trợ theo mặc định. Ví dụ: TogglePreferenceController có một API liên kết trực tiếp đến cách người dùng sẽ tương tác với giao diện người dùng ưu tiên dựa trên nút bật/tắt.

BasePreferenceController có các API như getAvailabilityStatus(), displayPreference(), handlePreferenceTreeClicked(),, v.v. Tài liệu chi tiết cho từng API nằm trong lớp giao diện.

Một hạn chế trong việc triển khai BasePreferenceController (và các lớp con của nó như TogglePreferenceController) là chữ ký của hàm khởi tạo phải khớp với một trong các giá trị sau:

  • public MyController(Context context, String key) {}
  • public MyController(Context context) {}

Trong khi cài đặt một lựa chọn ưu tiên cho mảnh, trang tổng quan sẽ cung cấp một phương thức để đính kèm PreferenceController trước thời gian hiển thị. Tại thời điểm cài đặt, tay điều khiển được kết nối với mảnh để tất cả các sự kiện có liên quan trong tương lai đều được gửi đến tay điều khiển.

DashboardFragment lưu giữ danh sách PreferenceController trên màn hình. Tại onCreate() của phân mảnh, tất cả tay điều khiển sẽ được gọi cho phương thức getAvailabilityStatus() và nếu phương thức này trả về giá trị true (đúng), displayPreference() sẽ được gọi để xử lý logic hiển thị. getAvailabilityStatus() cũng quan trọng để cho khung Cài đặt biết những mục nào có sẵn trong quá trình tìm kiếm.

PreferenceController trong các bản phát hành Android 8.x

PreferenceController chứa mọi logic để tương tác với lựa chọn ưu tiên, bao gồm cả việc hiển thị, cập nhật, lập chỉ mục tìm kiếm, v. v.

Tương ứng với các lượt tương tác với lựa chọn ưu tiên, giao diện của PreferenceController có các API isAvailable(), displayPreference(), handlePreferenceTreeClicked(), v.v. Bạn có thể xem tài liệu chi tiết về từng API trong lớp giao diện.

Trong khi cài đặt một lựa chọn ưu tiên cho mảnh, trang tổng quan sẽ cung cấp một phương thức để đính kèm PreferenceController trước thời gian hiển thị. Tại thời điểm cài đặt, tay điều khiển được kết nối với mảnh để tất cả các sự kiện có liên quan trong tương lai đều được gửi đến tay điều khiển.

DashboardFragment lưu giữ danh sách PreferenceControllers trên màn hình. Tại onCreate() của mảnh, tất cả bộ điều khiển được gọi cho phương thức isAvailable() và nếu phương thức này trả về giá trị true, displayPreference() sẽ được gọi để xử lý logic hiển thị.

Sử dụng DashboardFragment

Di chuyển lựa chọn ưu tiên từ trang A sang trang B

Nếu lựa chọn ưu tiên được liệt kê tĩnh trong tệp XML lựa chọn ưu tiên của trang gốc, hãy làm theo quy trình di chuyển Tĩnh cho bản phát hành Android ở bên dưới. Nếu không, hãy làm theo quy trình di chuyển Linh hoạt cho bản phát hành Android của bạn.

Di chuyển tĩnh trong Android 9

  1. Tìm các tệp XML lựa chọn ưu tiên cho trang gốc và trang đích. Bạn có thể tìm thấy thông tin này từ phương thức getPreferenceScreenResId() của trang.
  2. Hãy xoá lựa chọn ưu tiên này khỏi tệp XML của trang gốc.
  3. Thêm lựa chọn ưu tiên vào XML của trang đích.
  4. Xoá PreferenceController cho lựa chọn ưu tiên này khỏi phương thức triển khai Java của trang gốc. Thông thường, mã này nằm trong createPreferenceControllers(). Bạn có thể khai báo trực tiếp bộ điều khiển ở định dạng XML.

    Lưu ý: Lựa chọn ưu tiên có thể không có PreferenceController.

  5. Tạo thực thể cho PreferenceController trong createPreferenceControllers() của trang đích. Nếu PreferenceController được xác định trong XML trên trang cũ, hãy xác định mã đó trong XML cho trang mới.

Di chuyển linh động trong Android 9

  1. Tìm danh mục lưu trữ trang gốc và trang đích. Bạn có thể tìm thấy thông tin này trong DashboardFragmentRegistry.
  2. Mở tệp AndroidManifest.xml chứa chế độ cài đặt mà bạn cần di chuyển và tìm mục nhập Hoạt động đại diện cho chế độ cài đặt này.
  3. Đặt giá trị siêu dữ liệu của hoạt động cho com.android.settings.category thành khoá danh mục của trang mới.

Di chuyển tĩnh trong các bản phát hành Android 8.x

  1. Tìm các tệp XML tuỳ chọn cho trang gốc và trang đích.
  2. Bạn có thể tìm thấy thông tin này qua phương thức getPreferenceScreenResId() của trang.
  3. Xoá lựa chọn ưu tiên trong XML của trang gốc.
  4. Thêm lựa chọn ưu tiên vào XML của trang đích.
  5. Xoá PreferenceController cho lựa chọn ưu tiên này trong quá trình triển khai Java của trang gốc. Thường thì mục này nằm trong getPreferenceControllers().
  6. Lưu ý: Có thể lựa chọn ưu tiên không có PreferenceController.

  7. Tạo thực thể cho PreferenceController trong getPreferenceControllers() của trang đích.

Tính năng di chuyển động trong các bản phát hành Android 8.x

  1. Tìm danh mục lưu trữ trang gốc và trang đích. Bạn có thể tìm thấy thông tin này trong DashboardFragmentRegistry.
  2. Mở tệp AndroidManifest.xml chứa chế độ cài đặt mà bạn cần di chuyển và tìm mục nhập Hoạt động đại diện cho chế độ cài đặt này.
  3. Thay đổi giá trị siêu dữ liệu của hoạt động cho com.android.settings.category, đặt điểm giá trị thành khoá danh mục của trang mới.

Tạo lựa chọn ưu tiên mới trên một trang

Nếu lựa chọn ưu tiên được liệt kê tĩnh trong tệp XML lựa chọn ưu tiên của trang gốc, hãy làm theo quy trình tĩnh dưới đây. Nếu không, hãy làm theo quy trình động.

Tạo lựa chọn ưu tiên tĩnh

  1. Tìm các tệp XML lựa chọn ưu tiên cho trang đó. Bạn có thể tìm thấy thông tin này qua phương thức getPreferenceScreenResId() trên trang.
  2. Thêm một mục Lựa chọn ưu tiên mới trong tệp XML. Hãy đảm bảo tệp này có một android:key duy nhất.
  3. Hãy xác định PreferenceController cho lựa chọn ưu tiên này trong phương thức getPreferenceControllers() của trang.
    • Trong Android 8.x và trong Android 9 (không bắt buộc), hãy tạo thực thể PreferenceController cho lựa chọn ưu tiên này trong phương thức createPreferenceControllers() của trang.

      Nếu lựa chọn ưu tiên này đã tồn tại ở các vị trí khác, thì có thể đã có PreferenceController cho lựa chọn đó. Bạn có thể sử dụng lại PreferenceController mà không cần tạo một mã mới.

    • Kể từ Android 9, bạn có thể chọn khai báo PreferenceController trong XML bên cạnh lựa chọn ưu tiên. Ví dụ:
      <Preference
              android:key="reset_dashboard"
              android:title="@string/reset_dashboard_title"
              settings:controller="com.android.settings.system.ResetPreferenceController"/>
      

Tạo lựa chọn ưu tiên linh động

  1. Tìm danh mục lưu trữ trang gốc và trang đích. Bạn có thể tìm thấy thông tin này trong DashboardFragmentRegistry.
  2. Tạo một Hoạt động mới trong AndroidManifest
  3. Thêm siêu dữ liệu cần thiết vào Activity (Hoạt động) mới để xác định chế độ cài đặt. Đặt giá trị siêu dữ liệu cho com.android.settings.category thành chính giá trị đã xác định trong bước 1.

Tạo một trang mới

  1. Tạo một mảnh mới kế thừa từ DashboardFragment.
  2. Hãy xác định danh mục trong DashboardFragmentRegistry.

    Lưu ý: Đây là bước không bắt buộc. Nếu không cần lựa chọn ưu tiên linh động nào trong trang này, thì bạn không cần cung cấp khoá danh mục.

  3. Làm theo các bước để thêm chế độ cài đặt cần thiết cho trang này. Để biết thêm thông tin, hãy xem phần Triển khai.

Xác nhận kết quả

  • Chạy kiểm thử robolectric trong phần Cài đặt. Tất cả kiểm thử hiện tại và mới đều phải đạt.
  • Tạo và cài đặt phần Cài đặt, sau đó mở trang đang được sửa đổi theo cách thủ công. Trang sẽ cập nhật ngay lập tức.