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
- ค้นหาไฟล์ XML ค่ากำหนดสำหรับหน้าเดิมและหน้าปลายทาง คุณดูข้อมูลนี้ได้จากเมธอด
getPreferenceScreenResId()
ของหน้าเว็บ - นำค่ากำหนดออกจาก XML ของหน้าเดิม
- เพิ่มค่ากำหนดใน XML ของหน้าปลายทาง
- นำ
PreferenceController
สำหรับค่ากำหนดนี้ออกจากการใช้ Java ของหน้าเว็บเดิม โดยปกติจะอยู่ในcreatePreferenceControllers()
ตัวควบคุมอาจมีการประกาศใน XML โดยตรงหมายเหตุ: ค่ากำหนดอาจไม่มี
PreferenceController
- สร้างอินสแตนซ์
PreferenceController
ในcreatePreferenceControllers()
ของหน้าปลายทาง หากมีการกำหนดPreferenceController
ใน XML ในหน้าเก่า ให้กำหนดใน XML สำหรับหน้าใหม่ด้วย
การเคลื่อนไหวแบบไดนามิกใน Android 9
- ค้นหาหมวดหมู่ที่โฮสต์หน้าเดิมและหน้าปลายทาง คุณดูข้อมูลนี้ได้ใน
DashboardFragmentRegistry
- เปิดไฟล์
AndroidManifest.xml
ที่มีการตั้งค่าที่คุณต้องการย้าย และค้นหารายการกิจกรรมที่แสดงการตั้งค่านี้ - ตั้งค่าข้อมูลเมตาของกิจกรรมสำหรับ
com.android.settings.category
เป็นคีย์หมวดหมู่ของหน้าใหม่
การเคลื่อนไหวแบบคงที่ใน Android 8.x รุ่น
- ค้นหาไฟล์ XML ค่ากำหนดสำหรับหน้าเดิมและหน้าปลายทาง คุณดูข้อมูลนี้ได้จากเมธอด
- นำค่ากำหนดใน XML ของหน้าเดิมออก
- เพิ่มค่ากำหนดใน XML ของหน้าปลายทาง
- นำ
PreferenceController
สำหรับค่ากำหนดนี้ออกในการใช้งาน Java ของหน้าเว็บเดิม โดยปกติมักจะอยู่ในgetPreferenceControllers()
- สร้างอินสแตนซ์
PreferenceController
ในgetPreferenceControllers()
ของหน้าปลายทาง
getPreferenceScreenResId()
ของหน้าเว็บ
หมายเหตุ: อาจเป็นไปได้ว่าค่ากำหนดไม่มี PreferenceController
การเคลื่อนไหวแบบไดนามิกใน Android 8.x รุ่น
- ค้นหาหมวดหมู่ที่โฮสต์หน้าเดิมและหน้าปลายทาง คุณดูข้อมูลนี้ได้ใน
DashboardFragmentRegistry
- เปิดไฟล์
AndroidManifest.xml
ที่มีการตั้งค่าที่คุณต้องการย้าย และค้นหารายการกิจกรรมที่แสดงการตั้งค่านี้ - เปลี่ยนค่าข้อมูลเมตาของกิจกรรมสำหรับ
com.android.settings.category
กำหนดจุดค่าเป็นคีย์หมวดหมู่ของหน้าใหม่
สร้างค่ากำหนดใหม่ในหน้าเว็บ
หากค่ากำหนดดังกล่าวแสดงแบบคงที่ในไฟล์ XML ค่ากำหนดของหน้าเดิม ให้ทำตามขั้นตอนแบบคงที่ด้านล่าง หรือทำตามกระบวนการ dynamic
สร้างค่ากำหนดแบบคงที่
- ค้นหาไฟล์ XML ค่ากำหนดสำหรับหน้านั้น คุณสามารถดูข้อมูลนี้ได้จากเมธอด getPreferenceScreenResId() ของหน้าเว็บ
- เพิ่มรายการค่ากำหนดใหม่ใน XML โปรดตรวจสอบว่ามี
android:key
ที่ไม่ซ้ำกัน -
กำหนด
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"/>
- ใน Android 8.x และ Android 9 (ไม่บังคับ) ให้ยืนยัน
สร้างค่ากำหนดแบบไดนามิก
- ค้นหาหมวดหมู่ที่โฮสต์หน้าเดิมและหน้าปลายทาง คุณดูข้อมูลนี้ได้ใน
DashboardFragmentRegistry
- สร้างกิจกรรมใหม่ใน
AndroidManifest
- เพิ่มข้อมูลเมตาที่จำเป็นลงในกิจกรรมใหม่เพื่อกำหนดการตั้งค่า ตั้งค่าข้อมูลเมตาสำหรับ
com.android.settings.category
เป็นค่าเดียวกันกับที่กำหนดไว้ในขั้นตอนที่ 1
สร้างเพจใหม่
- สร้างส่วนย่อยใหม่ โดยรับค่าจาก
DashboardFragment
- กำหนดหมวดหมู่ใน
DashboardFragmentRegistry
หมายเหตุ: ขั้นตอนนี้เป็นแบบไม่บังคับ หากไม่ต้องการค่ากำหนดแบบไดนามิกใดๆ ในหน้านี้ คุณก็ไม่จำเป็นต้องระบุคีย์หมวดหมู่
- ทําตามขั้นตอนเพื่อเพิ่มการตั้งค่าที่จําเป็นสําหรับหน้านี้ ดูข้อมูลเพิ่มเติมได้ในส่วนการใช้งาน
การตรวจสอบความถูกต้อง
- ทำการทดสอบแบบ Robolectric ในการตั้งค่า การทดสอบที่มีอยู่และการทดสอบใหม่ทั้งหมดควรผ่าน
- สร้างและติดตั้งการตั้งค่า แล้วเปิดหน้าเว็บที่แก้ไขด้วยตนเอง หน้าเว็บควรอัปเดตทันที