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

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 จำเป็นต้องมีการทดสอบหน่วย หากต้องการข้อมูลเพิ่มเติมเกี่ยวกับวิธีการเขียนการทดสอบที่ใช้ Robolectric โปรดดูที่ไฟล์ readme packages/apps/Settings/tests/robotests/README.md

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

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

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

แดชบอร์ดแฟรกเมนต์

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

การตั้งค่าแบบคงที่

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

การตั้งค่าแบบไดนามิก

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

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

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

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

  • ทำเครื่องหมายกิจกรรมเป็นการตั้งค่าแบบไดนามิกโดยเพิ่มตัวกรองเจตนาให้กับกิจกรรม
  • บอกแอปการตั้งค่าว่าเป็นหมวดหมู่ใด หมวดหมู่นี้เป็นค่าคงที่ ซึ่งกำหนดไว้ใน 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 ใน 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 ) คือลายเซ็น Constructor ต้องตรงกับรายการใดรายการหนึ่งต่อไปนี้:

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

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

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

PreferenceController ใน Android 8.x เปิดตัว

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

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

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

DashboardFragment เก็บรายการ PreferenceControllers ไว้ในหน้าจอ ที่ onCreate() ของแฟรกเมนต์ คอนโทรลเลอร์ทั้งหมดจะถูกเรียกใช้สำหรับเมธอด isAvailable() และหากคืนค่าเป็น true ก็จะเรียกใช้ 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 ในการตั้งค่า การทดสอบที่มีอยู่และการทดสอบใหม่ทั้งหมดควรผ่าน
  • สร้างและติดตั้งการตั้งค่า จากนั้นเปิดเพจที่กำลังแก้ไขด้วยตนเอง เพจควรปรับปรุงทันที