สถาปัตยกรรมสารสนเทศ

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

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

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

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

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

ส่วนย่อยของแดชบอร์ด

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

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

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

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

รายการแบบไดนามิกแสดงการ์ดที่มีความตั้งใจ ซึ่งนำไปสู่กิจกรรมภายนอกหรือภายใน โดยปกติแล้ว 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 ค่ากำหนดของหน้าเดิม ให้ทำตามขั้นตอนแบบคงที่ด้านล่าง หรือทำตามกระบวนการ dynamic

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

  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 ในการตั้งค่า การทดสอบที่มีอยู่และการทดสอบใหม่ทั้งหมดควรผ่าน
  • สร้างและติดตั้งการตั้งค่า แล้วเปิดหน้าเว็บที่แก้ไขด้วยตนเอง หน้าเว็บควรอัปเดตทันที