สถาปัตยกรรมข้อมูล

Android 8.0 เปิดตัวสถาปัตยกรรมข้อมูลใหม่สำหรับแอปการตั้งค่าเพื่อลดความซับซ้อนของการจัดระเบียบการตั้งค่าและช่วยให้ผู้ใช้ค้นหาการตั้งค่าเพื่อปรับแต่งอุปกรณ์ Android ได้อย่างรวดเร็ว Android 9 มีการปรับปรุงบางอย่างเพื่อให้การตั้งค่ามีฟังก์ชันการทำงานมากขึ้นและติดตั้งใช้งานได้ง่ายขึ้น

ตัวอย่างและแหล่งที่มา

ปัจจุบันหน้าเว็บส่วนใหญ่ในการตั้งค่ามีการใช้งานโดยใช้เฟรมเวิร์กใหม่ ตัวอย่างที่ดีคือ DisplaySettings packages/apps/Settings/src/com/android/settings/DisplaySettings.java

เส้นทางไฟล์สําหรับคอมโพเนนต์ที่สําคัญมีดังนี้

  • CategoryKey: packages/SettingsLib/src/com/android/settingslib/drawer/CategoryKey.java
  • dashboardFragmentRegistry มีดังนี้ packages/apps/Settings/src/com/android/settings/dashboard/DashboardFragmentRegistry.java
  • dashboardFragment: packages/apps/Settings/src/com/android/settings/dashboard/DashboardFragment.java
  • AbstractPreferenceController: frameworks/base/packages/SettingsLib/src/com/android/settingslib/core/AbstractPreferenceController.java
  • BasePreferenceController (เปิดตัวใน Android 9) packages/apps/Settings/src/com/android/settings/core/BasePreferenceController.java

การใช้งาน

เราขอแนะนำให้ผู้ผลิตอุปกรณ์ปรับสถาปัตยกรรมข้อมูลการตั้งค่าที่มีอยู่และแทรกหน้าการตั้งค่าเพิ่มเติมตามที่จำเป็นเพื่อรองรับฟีเจอร์เฉพาะพาร์ทเนอร์ การย้ายค่ากําหนดจากหน้าเดิม (ติดตั้งใช้งานเป็น SettingsPreferencePage) ไปยังหน้าใหม่ (ติดตั้งใช้งานโดยใช้ DashboardFragment) อาจมีความซับซ้อน ค่ากำหนดจาก หน้าเดิมน่าจะยังไม่ได้ใช้กับ PreferenceController

ดังนั้นเมื่อย้ายค่ากําหนดจากหน้าเดิมไปยังหน้าใหม่ คุณจะต้องสร้าง PreferenceController แล้วย้ายโค้ดไปยังตัวควบคุมก่อนสร้างอินสแตนซ์ใน DashboardFragment ใหม่ API ที่ มีการอธิบายข้อกำหนด PreferenceController ในชื่อและ เป็นเอกสารใน Javadoc

เราขอแนะนําอย่างยิ่งให้เพิ่มการทดสอบหน่วยสําหรับ PreferenceController แต่ละรายการ หากส่งการเปลี่ยนแปลงไปยัง AOSP คุณต้องทำการทดสอบ 1 หน่วย หากต้องการข้อมูลเพิ่มเติมเกี่ยวกับวิธีเขียนการทดสอบที่อิงตาม Robolectric โปรดดูที่ ไฟล์ Readme packages/apps/Settings/tests/robotests/README.md

สถาปัตยกรรมข้อมูลแบบปลั๊กอิน

ระบบจะใช้การตั้งค่าแต่ละรายการเป็นค่ากำหนด คุณย้ายค่ากำหนดจากหน้าหนึ่งไปยังอีกหน้าหนึ่งได้โดยง่าย

Android 8.0 ได้เปิดตัวเศษส่วนของโฮสต์สไตล์ปลั๊กอินที่มีรายการการตั้งค่าเพื่อให้ย้ายการตั้งค่าหลายรายการได้ง่ายขึ้น รายการการตั้งค่าคือ โมเดลดังกล่าวเป็นตัวควบคุมรูปแบบปลั๊กอิน ดังนั้น หน้าการตั้งค่าจึงสร้างขึ้นโดย ส่วนย่อยของโฮสต์เดียวและตัวควบคุมการตั้งค่าหลายรายการ

DashboardFragment

DashboardFragment เป็นโฮสต์ของตัวควบคุมค่ากำหนดรูปแบบปลั๊กอิน ข้อมูลโค้ดรับค่ามาจาก PreferenceFragment และมีฮุกเพื่อขยายและอัปเดตทั้งรายการค่ากําหนดแบบคงที่และรายการค่ากําหนดแบบไดนามิก

ค่ากําหนดแบบคงที่

รายการค่ากำหนดแบบคงที่กำหนดไว้ใน XML โดยใช้แท็ก <Preference> ต การใช้งาน DashboardFragment ใช้เมธอด getPreferenceScreenResId() เมธอดในการกำหนดว่าไฟล์ XML ใดมี รายการค่ากำหนดแบบคงที่ที่จะแสดง

ค่ากำหนดแบบไดนามิก

รายการแบบไดนามิกแสดงการ์ดที่มี Intent ซึ่งนําไปสู่กิจกรรมภายนอกหรือภายใน โดยปกติแล้ว Intent จะนำไปยังหน้าการตั้งค่าอื่น ตัวอย่างเช่น "Google" รายการการตั้งค่าในหน้าแรกของการตั้งค่าเป็นรายการแบบไดนามิก ระบบจะกําหนดรายการแบบไดนามิกใน AndroidManifest (จะอธิบายด้านล่าง) และโหลดผ่าน FeatureProvider (กําหนดเป็น DashboardFeatureProvider)

การตั้งค่าแบบไดนามิกนั้นใช้ภาระงานหนักกว่าการกำหนดค่าแบบคงที่ ดังนั้นตามปกติแล้วนักพัฒนาซอฟต์แวร์ควรใช้การตั้งค่าแบบคงที่ อย่างไรก็ตาม การตั้งค่าแบบไดนามิกอาจมีประโยชน์เมื่อเงื่อนไขใดๆ ต่อไปนี้เป็นจริง

  • การตั้งค่านี้ไม่มีการใช้งานในแอปการตั้งค่าโดยตรง (เช่น การแทรกการตั้งค่าที่ใช้งานโดยแอป OEM/ผู้ให้บริการ)
  • การตั้งค่านี้ควรปรากฏในหน้าแรกของการตั้งค่า
  • คุณมีกิจกรรมสำหรับการตั้งค่านี้อยู่แล้ว และไม่ต้องการใช้ การกำหนดค่าแบบคงที่เพิ่มเติม

หากต้องการกําหนดค่ากิจกรรมเป็นการตั้งค่าแบบไดนามิก ให้ทําดังนี้

  • ทำเครื่องหมายกิจกรรมเป็นการตั้งค่าแบบไดนามิกโดยเพิ่มตัวกรอง Intent ลงใน กิจกรรม
  • บอกแอปการตั้งค่าว่าแอปนั้นอยู่ในหมวดหมู่ใด หมวดหมู่เป็นค่าคงที่ กำหนดไว้ในCategoryKey
  • ไม่บังคับ: เพิ่มข้อความสรุปเมื่อการตั้งค่าแสดงขึ้น

ต่อไปนี้คือตัวอย่างที่นำมาจากแอปการตั้งค่าสำหรับ 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>

ขณะแสดงผล ส่วนย่อยจะขอรายการค่ากำหนดจากทั้งแบบคงที่ XML และการตั้งค่าแบบไดนามิกที่กำหนดไว้ใน AndroidManifest ไม่ว่าจะเป็น PreferenceController ได้รับการกำหนดไว้ในโค้ด Java หรือใน XML DashboardFragment จะจัดการตรรกะการจัดการของการตั้งค่าแต่ละรายการ จนถึง PreferenceController (กล่าวถึงด้านล่าง) แล้วก็คือ แสดงใน UI เป็นรายการแบบผสม

PreferenceController

การติดตั้งใช้งาน PreferenceController นั้นมีความแตกต่างกัน ใน Android 9 และ Android 8.x ตามที่อธิบายไว้ใน

PreferenceController ใน Android 9 รุ่น

PreferenceController มีตรรกะทั้งหมดในการโต้ตอบกับ ค่ากำหนด ซึ่งรวมถึงการแสดง การอัปเดต การจัดทำดัชนีการค้นหา ฯลฯ

อินเทอร์เฟซของ PreferenceController หมายถึง BasePreferenceController ตัวอย่างเช่น ดูโค้ดใน packages/apps/Settings/src/com/android/settings/core/ BasePreferenceController.java

มีคลาสย่อยของ BasePreferenceController อยู่หลายคลาส แต่ละคลาส การแมปกับรูปแบบ UI ที่เฉพาะเจาะจงซึ่งแอปการตั้งค่ารองรับโดยค่าเริ่มต้น ตัวอย่างเช่น TogglePreferenceController มี API ที่เชื่อมโยงโดยตรงกับวิธีที่ผู้ใช้ควรโต้ตอบกับ UI ค่ากําหนดแบบปุ่มเปิด/ปิด

BasePreferenceController มี API เช่น getAvailabilityStatus() displayPreference() handlePreferenceTreeClicked(), ฯลฯ เอกสารโดยละเอียดสำหรับแต่ละ API อยู่ในคลาสอินเทอร์เฟซ

ข้อจำกัดในการใช้ BasePreferenceController (และ คลาสย่อย เช่น TogglePreferenceController) คือ ลายเซ็นตัวสร้างต้องตรงกับรายการใดรายการหนึ่งต่อไปนี้

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

ขณะติดตั้งค่ากําหนดในข้อมูลโค้ด แดชบอร์ดจะมีวิธีการแนบ PreferenceController ก่อนเวลาแสดง เมื่อมีการติดตั้ง ตัวควบคุมจะเชื่อมต่อกับชิ้นส่วนเพื่อให้ระบบส่งเหตุการณ์ที่เกี่ยวข้องทั้งหมดในอนาคตไปยังตัวควบคุม

DashboardFragment เก็บรายการ PreferenceControllerในหน้าจอ ที่ onCreate() ของข้อมูลโค้ดโค้ดจะเรียกใช้ตัวควบคุมทั้งหมดสําหรับเมธอด getAvailabilityStatus() และหากผลลัพธ์เป็น "จริง" ระบบจะเรียกใช้ displayPreference() เพื่อประมวลผลตรรกะการแสดงผล getAvailabilityStatus()ก็สำคัญต่อการบอกการตั้งค่า กำหนดรายการที่จะแสดงขณะค้นหา

PreferenceController ในรุ่น Android 8.x

PreferenceController มีตรรกะทั้งหมดในการโต้ตอบกับ ค่ากำหนด ซึ่งรวมถึงการแสดง การอัปเดต การจัดทำดัชนีการค้นหา อื่นๆ

อินเทอร์เฟซของ PreferenceController มี API isAvailable(), displayPreference(), handlePreferenceTreeClicked() ฯลฯ ซึ่งสอดคล้องกับการโต้ตอบกับค่ากําหนด ดูเอกสารประกอบโดยละเอียดเกี่ยวกับ API แต่ละรายการได้ในคลาสอินเทอร์เฟซ

ขณะติดตั้งค่ากำหนดลงในส่วนย่อย หน้าแดชบอร์ดมีวิธีในการ แนบ PreferenceController ก่อนเวลาแสดง ณ เวลาติดตั้ง ตัวควบคุมต่อสายไฟเข้ากับส่วนย่อย ดังนั้นเหตุการณ์ที่เกี่ยวข้องในอนาคตทั้งหมดจึง ที่ส่งไปยังตัวควบคุม

DashboardFragment เก็บรายการ PreferenceControllers ไว้ในหน้าจอ ที่ onCreate() ของข้อมูลโค้ดแบบเป็นกลุ่ม ระบบจะเรียกใช้ตัวควบคุมทั้งหมดสําหรับเมธอด isAvailable() และหากผลลัพธ์เป็น "จริง" ระบบจะเรียกใช้ displayPreference() เพื่อประมวลผลตรรกะการแสดงผล

ใช้ DashboardFragment

ย้ายค่ากำหนดจากหน้า A ไป B

หากค่ากําหนดแสดงอยู่ในไฟล์ XML ของค่ากําหนดของหน้าเดิมแบบคงที่ ให้ทําตามขั้นตอนการย้ายแบบคงที่สําหรับรุ่น Android ด้านล่าง หรือทำตามขั้นตอนการย้ายแบบไดนามิกสำหรับรุ่น Android

การเคลื่อนไหวแบบคงที่ใน Android 9

  1. ค้นหาไฟล์ XML ค่ากำหนดสำหรับหน้าเดิมและปลายทาง คุณดูข้อมูลนี้ได้จาก getPreferenceScreenResId() วิธี
  2. นำค่ากำหนดออกจาก XML ของหน้าเดิม
  3. เพิ่มค่ากําหนดลงใน XML ของหน้าปลายทาง
  4. นำ PreferenceController สำหรับค่ากำหนดนี้ออกจาก การใช้ Java ของหน้าเว็บเดิม โดยปกติจะอยู่ใน createPreferenceControllers() ตัวควบคุมอาจประกาศใน XML โดยตรง

    หมายเหตุ: ค่ากำหนดอาจไม่มีค่า PreferenceController

  5. สร้างอินสแตนซ์ PreferenceController ใน createPreferenceControllers() ของหน้าปลายทาง หากมีการกําหนด PreferenceController ใน XML ในหน้าเก่า ให้กําหนดใน XML สําหรับหน้าใหม่ด้วย

การเคลื่อนไหวแบบไดนามิกใน Android 9

  1. ค้นหาหมวดหมู่ที่โฮสต์หน้าเดิมและหน้าปลายทาง คุณดูข้อมูลนี้ได้ใน DashboardFragmentRegistry
  2. เปิดไฟล์ AndroidManifest.xml ที่มีการตั้งค่าที่คุณ ต้องย้ายและค้นหารายการกิจกรรมที่แสดงการตั้งค่านี้
  3. ตั้งค่าข้อมูลเมตาของกิจกรรมสำหรับ com.android.settings.category ไปยังคีย์หมวดหมู่ของหน้าใหม่

การเคลื่อนไหวแบบคงที่ในรุ่น Android 8.x

  1. ค้นหาไฟล์ XML ค่ากำหนดสำหรับหน้าเดิมและหน้าปลายทาง
  2. คุณดูข้อมูลนี้ได้จากเมธอด getPreferenceScreenResId() ของหน้าเว็บ
  3. นำค่ากำหนดใน XML ของหน้าต้นฉบับออก
  4. เพิ่มค่ากําหนดลงใน XML ของหน้าปลายทาง
  5. นำ PreferenceController สำหรับค่ากำหนดนี้ออกใน การใช้ Java ของหน้าเว็บเดิม โดยทั่วไปจะอยู่ใน getPreferenceControllers()
  6. หมายเหตุ: อาจเป็นไปได้ว่าค่ากำหนดดังกล่าวไม่มี PreferenceController

  7. สร้างอินสแตนซ์ PreferenceController ในแท็กของหน้าปลายทาง getPreferenceControllers()

การเคลื่อนไหวแบบไดนามิกใน Android 8.x รุ่น

  1. ค้นหาหมวดหมู่ที่โฮสต์หน้าเดิมและหน้าปลายทาง คุณดูข้อมูลนี้ได้ใน DashboardFragmentRegistry
  2. เปิดไฟล์ AndroidManifest.xml ที่มีการตั้งค่าที่คุณต้องย้าย แล้วค้นหารายการกิจกรรมที่แสดงถึงการตั้งค่านี้
  3. เปลี่ยนค่าข้อมูลเมตาของกิจกรรมสําหรับ com.android.settings.category โดยตั้งค่าจุดค่าเป็นคีย์หมวดหมู่ของหน้าเว็บใหม่

สร้างค่ากําหนดใหม่ในหน้าเว็บ

หากค่ากำหนดนั้นระบุแบบคงที่ใน XML ค่ากำหนดของหน้าเดิม โปรดทำตามขั้นตอนแบบคงที่ด้านล่าง หรือทำตาม ไดนามิก

สร้างค่ากำหนดแบบคงที่

  1. ค้นหาไฟล์ XML ของค่ากําหนดสําหรับหน้าเว็บ คุณดูข้อมูลนี้ได้จากเมธอด getPreferenceScreenResId() ของหน้า
  2. เพิ่มรายการค่ากําหนดใหม่ใน XML ตรวจสอบว่า android:key ของช่องไม่ซ้ำกัน
  3. กำหนด PreferenceController สำหรับค่ากำหนดนี้ในองค์ประกอบ getPreferenceControllers() วิธี
    • ใน Android 8.x และ Android 9 (ไม่บังคับ) ให้สร้างอินสแตนซ์ PreferenceController สำหรับค่ากําหนดนี้ในเมธอด createPreferenceControllers() ของหน้า

      หากมีค่ากำหนดนี้อยู่แล้วในที่อื่น อาจเป็นไปได้ว่า PreferenceControllerอยู่แล้ว คุณนําPreferenceControllerไปใช้ซ้ำได้โดยไม่ต้องสร้างใหม่

    • ตั้งแต่ Android 9 เป็นต้นไป คุณเลือกที่จะประกาศ PreferenceController ใน XML ถัดจากค่ากำหนด เช่น
      <Preference
              android:key="reset_dashboard"
              android:title="@string/reset_dashboard_title"
              settings:controller="com.android.settings.system.ResetPreferenceController"/>

สร้างค่ากำหนดแบบไดนามิก

  1. ดูว่าหน้าต้นทางและหน้าปลายทางอยู่ในหมวดหมู่ใด คุณดูข้อมูลนี้ได้ใน DashboardFragmentRegistry
  2. สร้างกิจกรรมใหม่ใน AndroidManifest
  3. เพิ่มข้อมูลเมตาที่จําเป็นลงในกิจกรรมใหม่เพื่อกําหนดการตั้งค่า ตั้งค่าค่าข้อมูลเมตาของ com.android.settings.category เป็นค่าเดียวกับที่กําหนดไว้ในขั้นตอนที่ 1

สร้างเพจใหม่

  1. สร้างส่วนย่อยใหม่โดยรับค่ามาจาก DashboardFragment
  2. กำหนดหมวดหมู่ใน DashboardFragmentRegistry

    หมายเหตุ: ขั้นตอนนี้เป็นแบบไม่บังคับ หากไม่ต้องการค่ากําหนดแบบไดนามิกในหน้านี้ คุณก็ไม่จําเป็นต้องระบุคีย์หมวดหมู่

  3. ทําตามขั้นตอนเพื่อเพิ่มการตั้งค่าที่จําเป็นสําหรับหน้านี้ สำหรับข้อมูลเพิ่มเติม โปรดดูที่ส่วนการใช้งาน

การตรวจสอบความถูกต้อง

  • ทำการทดสอบแบบ Robolectric ในการตั้งค่า การทดสอบที่มีอยู่และใหม่ทั้งหมดควรผ่าน
  • บิลด์และติดตั้งการตั้งค่า จากนั้นเปิดหน้าเว็บที่จะแก้ไขด้วยตนเอง หน้าเว็บควรอัปเดตทันที