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