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 ได้เปิดตัว โฮสต์ Fragment ในรูปแบบปลั๊กอินที่มีรายการการตั้งค่า เพื่อให้ย้ายการตั้งค่าหลายรายการได้ง่ายขึ้น รายการการตั้งค่าได้รับการ จำลองเป็นตัวควบคุมสไตล์ปลั๊กอิน ดังนั้น หน้าการตั้งค่าจึงสร้างขึ้นจาก โฮสต์แฟรกเมนต์เดียวและตัวควบคุมการตั้งค่าหลายตัว
DashboardFragment
DashboardFragment
เป็นโฮสต์ของตัวควบคุมค่ากำหนดสไตล์ปลั๊กอิน
Fragment จะรับค่ามาจาก PreferenceFragment
และมี Hook สำหรับ
ขยายและอัปเดตทั้งรายการค่ากำหนดแบบคงที่และรายการค่ากำหนดแบบไดนามิก
ค่ากำหนดแบบคงที่
คุณกำหนดรายการค่ากำหนดแบบคงที่ได้ใน 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>
เมื่อถึงเวลาระบบแสดงผล Fragment จะขอรายการค่ากำหนดจากทั้ง XML แบบคงที่
และการตั้งค่าแบบไดนามิกที่กำหนดไว้ใน AndroidManifest
ไม่ว่าจะกำหนดในโค้ด Java หรือใน XML
DashboardFragment
จะจัดการตรรกะการจัดการของการตั้งค่าแต่ละรายการ
ผ่าน PreferenceController
(อธิบายไว้ด้านล่าง)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) {}
ขณะติดตั้งค่ากำหนดไปยัง Fragment แดชบอร์ดจะมีวิธี
แนบ PreferenceController
ก่อนเวลาแสดง ในเวลาที่ติดตั้ง
ตัวควบคุมจะเชื่อมต่อกับ Fragment เพื่อให้ระบบส่งเหตุการณ์ที่เกี่ยวข้องทั้งหมดในอนาคต
ไปยังตัวควบคุม
DashboardFragment
จะเก็บรายการของ
PreferenceController
ในหน้าจอ ที่
onCreate()
ของ Fragment ระบบจะเรียกใช้ตัวควบคุมทั้งหมดสำหรับเมธอด
getAvailabilityStatus()
และหากเมธอดแสดงผลเป็นจริง
displayPreference()
จะได้รับการเรียกใช้เพื่อประมวลผลตรรกะการแสดงผล
getAvailabilityStatus()
ยังมีความสำคัญในการบอกเฟรมเวิร์กการตั้งค่า
ว่ารายการใดบ้างที่พร้อมใช้งานในระหว่างการค้นหา
PreferenceController ใน Android เวอร์ชัน 8.x
PreferenceController
มีตรรกะทั้งหมดในการโต้ตอบกับค่ากำหนด ซึ่งรวมถึงการแสดง การอัปเดต การจัดทำดัชนีการค้นหา ฯลฯ
อินเทอร์เฟซของ
PreferenceController
มี API isAvailable()
,
displayPreference()
, handlePreferenceTreeClicked()
ฯลฯ ซึ่งสอดคล้องกับการโต้ตอบตามค่ากำหนด
ดูเอกสารประกอบโดยละเอียดเกี่ยวกับ API แต่ละรายการได้ในคลาสอินเทอร์เฟซ
ขณะติดตั้งค่ากำหนดไปยัง Fragment แดชบอร์ดจะมีวิธี
แนบ PreferenceController
ก่อนเวลาแสดง ในเวลาที่ติดตั้ง
ตัวควบคุมจะเชื่อมต่อกับ Fragment เพื่อให้ระบบส่งเหตุการณ์ที่เกี่ยวข้องทั้งหมดในอนาคต
ไปยังตัวควบคุม
DashboardFragment
จะเก็บรายการ PreferenceControllers
ไว้ในหน้าจอ ที่ onCreate()
ของ Fragment ระบบจะเรียกใช้ตัวควบคุมทั้งหมดสำหรับเมธอด isAvailable()
และหากเมธอดนี้แสดงผลเป็นจริง ระบบจะเรียกใช้ displayPreference()
เพื่อประมวลผลตรรกะการแสดงผล
ใช้ DashboardFragment
ย้ายค่ากำหนดจากหน้า ก ไปยังหน้า ข
หากค่ากำหนดแสดงแบบคงที่ในไฟล์ 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
สร้างเพจใหม่
- สร้าง Fragment ใหม่โดยรับค่ามาจาก
DashboardFragment
- กำหนดหมวดหมู่ใน
DashboardFragmentRegistry
หมายเหตุ: ขั้นตอนนี้เป็นขั้นตอนที่ไม่บังคับ หากไม่ต้องการ ค่ากําหนดแบบไดนามิกในหน้านี้ คุณไม่จําเป็นต้องระบุคีย์หมวดหมู่
- ทำตามขั้นตอนเพื่อเพิ่มการตั้งค่าที่จำเป็นสำหรับหน้านี้ ดูข้อมูลเพิ่มเติมได้ที่ส่วนการติดตั้งใช้งาน
การตรวจสอบความถูกต้อง
- เรียกใช้การทดสอบ Robolectric ในการตั้งค่า การทดสอบที่มีอยู่และใหม่ทั้งหมดควร ผ่าน
- สร้างและติดตั้งการตั้งค่า จากนั้นเปิดหน้าเว็บที่จะแก้ไขด้วยตนเอง หน้าเว็บควรจะอัปเดตทันที