معماری اطلاعات

در 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 جدید به کنترل‌کننده منتقل کنید. میاناهای برنامه‌سازی کاربردی که PreferenceController نیاز دارد در نام آن‌ها شرح داده شده است و در Javadoc مستند شده است.

به‌شدت توصیه می‌شود برای هر PreferenceController آزمون واحد اضافه کنید. اگر تغییر به AOSP ارسال شود، آزمون واحد لازم است. برای دریافت اطلاعات بیشتر درباره نحوه نوشتن آزمایش‌های مبتنی بر Robolectric، فایل readme packages/apps/Settings/tests/robotests/README.md را ببینید.

معماری اطلاعات به‌سبک افزایه

هر مورد تنظیمات به‌عنوان «اولویت» پیاده‌سازی می‌شود. «اولویت» را به‌راحتی می‌توان از صفحه‌ای به صفحه دیگر منتقل کرد.

برای آسان‌تر کردن جابه‌جایی تنظیمات متعدد، Android 8.0 قطعه میزبان سبک افزایه‌ای را معرفی کرد که حاوی موارد تنظیمات است. موارد «تنظیمات» به‌عنوان کنترل‌کننده‌های سبک افزایه مدل‌سازی می‌شوند. بنابراین، صفحه تنظیمات از یک تکه میزبان واحد و چندین کنترل‌کننده تنظیمات ساخته می‌شود.

DashboardFragment

DashboardFragment میزبان کنترل‌کننده‌های اولویت سبک افزونه است. این تکه از PreferenceFragment به‌ارث می‌برد و قلاب‌هایی برای ازهم بازکردن و به‌روزرسانی هم فهرست‌های اولویت ایستا و هم فهرست‌های اولویت پویا دارد.

اولویت‌های ایستا

فهرست اولویت‌های ایستا در XML بااستفاده از برچسب <Preference> تعریف می‌شود. پیاده‌سازی DashboardFragment از روش getPreferenceScreenResId() برای تعریف اینکه کدام فایل XML حاوی فهرست ثابت اولویت‌ها برای نمایش است استفاده می‌کند.

اولویت‌های پویا

مورد پویا نشان‌دهنده کاشی‌ای با قصد است که به «فعالیت» خارجی یا داخلی منتهی می‌شود. معمولاً، هدف به صفحه تنظیمات دیگری منتهی می‌شود. برای مثال، مورد تنظیمات «Google» در صفحه اصلی «تنظیمات» موردی پویا است. عناصر پویا در AndroidManifest تعریف می‌شوند (در زیر بحث شده است) و ازطریق FeatureProvider (تعریف‌شده به‌عنوان DashboardFeatureProvider) بار می‌شوند.

تنظیمات پویا نسبت‌به تنظیمات پیکربندی‌شده ایستا سنگین‌تر هستند، بنابراین معمولاً توسعه‌دهندگان باید تنظیم را به‌صورت ایستا پیاده‌سازی کنند. بااین‌حال، تنظیم پویا زمانی می‌تواند مفید باشد که هریک از موارد زیر درست باشد:

  • این تنظیم مستقیماً در برنامه «تنظیمات» پیاده‌سازی نشده باشد (مثلاً تزریق تنظیم پیاده‌سازی‌شده توسط برنامه‌های «تولیدکننده تجهیزات اصلی»/ شرکت مخابراتی).
  • این تنظیم باید در صفحه اصلی «تنظیمات» نشان داده شود.
  • ازقبل «فعالیتی» برای تنظیم دارید و نمی‌خواهید پیکربندی ایستای اضافی را پیاده‌سازی کنید.

برای پیکربندی «فعالیت» به‌عنوان تنظیم پویا، مراحل زیر را انجام دهید:

  • با افزودن فیلتر هدف به فعالیت، آن را به‌عنوان تنظیم پویا علامت‌گذاری کنید.
  • به برنامه «تنظیمات» بگویید به کدام دسته تعلق دارد. دسته ثابت است، در 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ها در کد جاوا تعریف شده باشند چه در XML، DashboardFragment منطق مدیریت هر تنظیم را ازطریق PreferenceController (که در زیر بحث شده است) مدیریت می‌کند. سپس در میانای کاربری به‌صورت فهرست مختلط نمایش داده می‌شوند.

PreferenceController

همان‌طور که در این بخش توضیح داده شده است، بین پیاده‌سازی PreferenceController در Android 9 و Android 8.x تفاوت‌هایی وجود دارد.

‫PreferenceController در نسخه Android 9

PreferenceController شامل همه منطق‌های تعامل با اولویت، ازجمله نمایش، به‌روزرسانی، نمایه‌گذاری جستجو، و غیره است.

میانای PreferenceController به‌صورت BasePreferenceController تعریف شده است. برای مثال، کد را در packages/apps/Settings/src/com/android/settings/core/ BasePreferenceController.java ببینید

چندین زیرکلاس از BasePreferenceController وجود دارد که هرکدام به سبک واسط کاربر خاصی که برنامه «تنظیمات» به‌طور پیش‌فرض پشتیبانی می‌کند نگاشت می‌شود. برای مثال، TogglePreferenceController دارای یک میانای برنامه‌سازی کاربردی است که مستقیماً به نحوه تعامل کاربر با واسط کاربر اولویت مبتنی بر کلید اختصاص دارد.

‫BasePreferenceController میاناهای برنامه‌سازی کاربردی مانند getAvailabilityStatus()، displayPreference()، handlePreferenceTreeClicked(), و غیره دارد. مستندات دقیق برای هر میانای برنامه‌سازی کاربردی در کلاس میانای برنامه‌سازی کاربردی است.

محدودیت در پیاده‌سازی 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 دارای میاناهای برنامه‌سازی کاربردی isAvailable()، displayPreference()، handlePreferenceTreeClicked() و غیره است. مستندات دقیق درباره هر میانای برنامه‌سازی کاربردی را می‌توانید در کلاس رابط پیدا کنید.

هنگام نصب اولویت در قطعه، داشبورد روشی برای پیوست کردن PreferenceController قبل‌از زمان نمایش ارائه می‌دهد. در زمان نصب، کنترل‌کننده به قطعه متصل می‌شود تا همه رویدادهای مرتبط آینده به کنترل‌کننده ارسال شود.

DashboardFragment فهرستی از PreferenceControllers را در صفحه نگه می‌دارد. در onCreate() قطعه، همه کنترل‌کننده‌ها برای روش isAvailable() فراخوانده می‌شوند، و اگر «درست» برگرداند، displayPreference() برای پردازش منطق نمایش فراخوانده می‌شود.

استفاده از DashboardFragment

انتقال اولویت از صفحه الف به ب

اگر اولویت به‌صورت ایستا در فایل 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 نسخه ۸.x و به‌صورت اختیاری در Android نسخه ۹، یک 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. تکه‌کد جدیدی ایجاد کنید که از DashboardFragment ارث می‌برد.
  2. دسته آن را در DashboardFragmentRegistry تعریف کنید.

    توجه: این مرحله اختیاری است. اگر در این صفحه به هیچ اولویت پویایی نیاز ندارید، لازم نیست کلید دسته‌ای ارائه دهید.

  3. مراحل افزودن تنظیمات موردنیاز برای این صفحه را دنبال کنید. برای اطلاعات بیشتر، به بخش پیاده‌سازی مراجعه کنید.

اعتبارسنجی

  • آزمایش‌های robolectric را در «تنظیمات» اجرا کنید. همه آزمایش‌های موجود و جدید باید موفق باشند.
  • «تنظیمات» را بسازید و نصب کنید، سپس صفحه‌ای را که اصلاح می‌شود به‌صورت دستی باز کنید. صفحه باید بلافاصله به‌روز شود.