ساختار اطلاعات

اندروید ۸.۰ معماری اطلاعات جدیدی را برای برنامه تنظیمات معرفی کرد تا نحوه سازماندهی تنظیمات را ساده‌تر کند و کاربران بتوانند به سرعت تنظیمات را برای سفارشی‌سازی دستگاه‌های اندرویدی خود پیدا کنند. اندروید ۹ بهبودهایی را برای ارائه قابلیت‌های بیشتر تنظیمات و پیاده‌سازی آسان‌تر ارائه داد.

مثال‌ها و منابع

بیشتر صفحات در تنظیمات در حال حاضر با استفاده از چارچوب جدید پیاده‌سازی شده‌اند. یک مثال خوب DisplaySettings است: packages/apps/Settings/src/com/android/settings/DisplaySettings.java

مسیرهای فایل‌ها برای اجزای مهم در زیر فهرست شده‌اند:

  • کلید دسته‌بندی : 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
  • کنترل‌کننده‌ی اولویت انتزاعی : frameworks/base/packages/SettingsLib/src/com/android/settingslib/core/AbstractPreferenceController.java
  • BasePreferenceController (معرفی شده در اندروید ۹): packages/apps/Settings/src/com/android/settings/core/BasePreferenceController.java

پیاده‌سازی

به تولیدکنندگان دستگاه توصیه می‌شود که معماری اطلاعات تنظیمات موجود را تطبیق داده و در صورت نیاز صفحات تنظیمات اضافی را برای تطبیق با ویژگی‌های خاص شریک وارد کنند. انتقال تنظیمات از صفحه قدیمی (که به عنوان SettingsPreferencePage پیاده‌سازی شده است) به یک صفحه جدید (که با استفاده از DashboardFragment پیاده‌سازی شده است) می‌تواند پیچیده باشد. تنظیمات از صفحه قدیمی احتمالاً با PreferenceController پیاده‌سازی نشده است.

بنابراین هنگام انتقال یک preferences از یک صفحه legacy به یک صفحه جدید، باید یک PreferenceController ایجاد کنید و کد را قبل از نمونه‌سازی آن در DashboardFragment جدید، به کنترلر منتقل کنید. APIهایی که PreferenceController نیاز دارد، با نام خود شرح داده شده و در Javadoc مستند شده‌اند.

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

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

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

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

قطعه داشبورد

DashboardFragment میزبان کنترلرهای ترجیحات به سبک افزونه است. این قطعه کد از PreferenceFragment ارث بری می‌کند و دارای قلاب‌هایی برای گسترش و به‌روزرسانی لیست‌های ترجیحات استاتیک و لیست‌های ترجیحات پویا است.

تنظیمات استاتیک

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

تنظیمات پویا

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

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

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

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

  • با اضافه کردن یک intent-filter به activity، آن activity را به عنوان یک محیط پویا علامت گذاری کنید.
  • به برنامه تنظیمات بگویید که به کدام دسته تعلق دارد. دسته یک ثابت است که در CategoryKey تعریف شده است.
  • اختیاری: هنگام نمایش تنظیمات، متن خلاصه اضافه کنید.

در اینجا مثالی از برنامه تنظیمات برای DisplaySettings آورده شده است.

<activity android:name="Settings$DisplaySettingsActivity"
                   android:label="@string/display_settings"
                   android:icon="@draw>able/ic_settin<gs_display"
             !-- Mark the ac>tivity as a dyn<amic setting >--
              inten<t-filter
                     action android:name="com.and>roid.settings.a<ction.IA_SETTI>NGS" /
  <            /intent-filter
             !-- Tell Sett>ings app which <category it belongs to --
              meta-data android:name="com.android.settings.category"
                     android:v>alue="com<.android.settings.category.ia.homepage" /
        >     !-- Add a <summary text when the setting is displayed --
              meta-data android:name="com.android.settings.summary"
    >              <   androi>d:resource="@string/display_dashboard_summary"/
             /activity

در زمان رندر، این قطعه کد، لیستی از تنظیمات Preferences را از هر دو نوع XML استاتیک و تنظیمات پویای تعریف شده در AndroidManifest درخواست می‌کند. چه PreferenceController ها در کد جاوا تعریف شده باشند و چه در XML، DashboardFragment منطق مدیریت هر تنظیم را از طریق PreferenceController (که در ادامه مورد بحث قرار می‌گیرد) مدیریت می‌کند. سپس آنها در رابط کاربری به صورت یک لیست ترکیبی نمایش داده می‌شوند.

کنترل‌کننده‌ی ترجیحی

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

PreferenceController در نسخه اندروید ۹

یک PreferenceController شامل تمام منطق لازم برای تعامل با preferences، از جمله نمایش، به‌روزرسانی، فهرست‌بندی جستجو و غیره است.

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

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

BasePreferenceController دارای APIهایی مانند getAvailabilityStatus() ، displayPreference() ، handlePreferenceTreeClicked(), و غیره است. مستندات دقیق هر API در کلاس رابط (interface class) قرار دارد.

محدودیتی که در پیاده‌سازی BasePreferenceController (و زیرکلاس‌های آن مانند TogglePreferenceController ) وجود دارد این است که امضای سازنده باید با یکی از موارد زیر مطابقت داشته باشد:

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

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

DashboardFragment فهرستی از PreferenceController ها را در صفحه نگه می‌دارد. در تابع onCreate() مربوط به fragment، تمام کنترلرها برای متد getAvailabilityStatus() فراخوانی می‌شوند و اگر مقدار true برگرداند، displayPreference() برای پردازش منطق نمایش فراخوانی می‌شود. getAvailabilityStatus() همچنین برای اطلاع‌رسانی به چارچوب تنظیمات که کدام آیتم‌ها در طول جستجو در دسترس هستند، مهم است.

PreferenceController در نسخه‌های اندروید ۸.x

یک PreferenceController شامل تمام منطق لازم برای تعامل با preferences، از جمله نمایش، به‌روزرسانی، فهرست‌بندی جستجو و غیره است.

مطابق با تعاملات ترجیحی، رابط کاربری PreferenceController دارای APIهایی isAvailable() ، displayPreference() ، handlePreferenceTreeClicked() و غیره است. مستندات دقیق هر API را می‌توان در کلاس رابط کاربری یافت.

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

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

استفاده از DashboardFragment

یک ترجیح را از صفحه A به صفحه B منتقل کنید

اگر ترجیح به صورت ایستا در فایل XML ترجیح صفحه اصلی فهرست شده است، روش حرکت ایستا را برای نسخه اندروید خود در زیر دنبال کنید. در غیر این صورت، روش حرکت پویا را برای نسخه اندروید خود دنبال کنید.

حرکت استاتیک در اندروید ۹

  1. فایل‌های XML مربوط به preferences صفحه اصلی و صفحه مقصد را پیدا کنید. می‌توانید این اطلاعات را از متد getPreferenceScreenResId() صفحه پیدا کنید.
  2. ترجیح را از XML صفحه اصلی حذف کنید.
  3. ترجیح را به XML صفحه مقصد اضافه کنید.
  4. PreferenceController مربوط به این preferences را از پیاده‌سازی جاوای صفحه اصلی حذف کنید. معمولاً در createPreferenceControllers() قرار دارد. کنترلر ممکن است مستقیماً در XML تعریف شده باشد.

    نکته : ممکن است preference دارای PreferenceController نباشد.

  5. نمونه‌ای PreferenceController در تابع createPreferenceControllers() صفحه مقصد ایجاد کنید. اگر PreferenceController در صفحه قدیمی به صورت XML تعریف شده است، آن را برای صفحه جدید نیز به صورت XML تعریف کنید.

حرکت پویا در اندروید ۹

  1. پیدا کنید که صفحه اصلی و صفحه مقصد میزبان کدام دسته هستند. می‌توانید این اطلاعات را در DashboardFragmentRegistry پیدا کنید.
  2. فایل AndroidManifest.xml که حاوی تنظیماتی است که باید جابجا کنید را باز کنید و ورودی Activity که نشان‌دهنده‌ی این تنظیمات است را پیدا کنید.
  3. مقدار فراداده‌ی فعالیت برای com.android.settings.category را برابر با کلید دسته‌بندی صفحه‌ی جدید تنظیم کنید.

حرکت استاتیک در نسخه‌های اندروید ۸.x

  1. فایل‌های XML ترجیحی را برای صفحه اصلی و صفحه مقصد پیدا کنید.
  2. شما می‌توانید این اطلاعات را از متد getPreferenceScreenResId() صفحه پیدا کنید.
  3. ترجیح را در XML صفحه اصلی حذف کنید.
  4. اولویت را به XML صفحه مقصد اضافه کنید.
  5. PreferenceController مربوط به این preferences را در پیاده‌سازی جاوای صفحه اصلی حذف کنید. معمولاً در getPreferenceControllers() قرار دارد.
  6. نکته: ممکن است preference فاقد PreferenceController باشد.

  7. نمونه‌ای از PreferenceController در تابع getPreferenceControllers() صفحه مقصد ایجاد کنید.

حرکت پویا در نسخه‌های اندروید ۸.x

  1. پیدا کنید که صفحه اصلی و صفحه مقصد میزبان کدام دسته هستند. می‌توانید این اطلاعات را در DashboardFragmentRegistry پیدا کنید.
  2. فایل AndroidManifest.xml که حاوی تنظیماتی است که باید جابجا کنید را باز کنید و ورودی Activity که نشان‌دهنده‌ی این تنظیمات است را پیدا کنید.
  3. مقدار فراداده‌ی فعالیت را برای com.android.settings.category تغییر دهید، و مقدار نقطه را روی کلید دسته‌بندی صفحه جدید تنظیم کنید.

ایجاد یک ترجیح جدید در یک صفحه

اگر ترجیح به صورت ایستا در فایل XML ترجیح صفحه اصلی فهرست شده است، از روش ایستا زیر پیروی کنید. در غیر این صورت، از روش پویا پیروی کنید.

ایجاد یک ترجیح ثابت

  1. فایل‌های XML مربوط به تنظیمات صفحه را پیدا کنید. می‌توانید این اطلاعات را از متد getPreferenceScreenResId() صفحه پیدا کنید.
  2. یک آیتم Preference جدید در XML اضافه کنید. مطمئن شوید که یک android:key منحصر به فرد دارد.
  3. یک PreferenceController برای این preference در متد getPreferenceControllers() صفحه تعریف کنید.
    • در اندروید ۸.x و به صورت اختیاری در اندروید ۹، یک PreferenceController برای این preference در متد createPreferenceControllers() صفحه نمونه‌سازی کنید.

      اگر این preferences از قبل در جاهای دیگر وجود داشته باشد، ممکن است از قبل یک PreferenceController برای آن وجود داشته باشد. می‌توانید بدون ساختن یک PreferenceController جدید، از PreferenceController دوباره استفاده کنید.

    • از اندروید ۹ به بعد، می‌توانید PreferenceController در قالب XML و در کنار preferences تعریف کنید. برای مثال:
      <Preference
              android:key="reset_dashboard"
              android:title="@string/reset_dashboard_title"
              settings:controller="com.android.settings.system.Re>setPreferenceController"/

ایجاد یک ترجیح پویا

  1. پیدا کنید که صفحه اصلی و صفحه مقصد میزبان کدام دسته هستند. می‌توانید این اطلاعات را در DashboardFragmentRegistry پیدا کنید.
  2. ایجاد یک اکتیویتی جدید در AndroidManifest
  3. برای تعریف تنظیمات، متادیتای لازم را به Activity جدید اضافه کنید. مقدار متادیتای com.android.settings.category را برابر با همان مقداری که در مرحله ۱ تعریف شد، قرار دهید.

ایجاد یک صفحه جدید

  1. یک قطعه کد جدید ایجاد کنید که از DashboardFragment ارث‌بری کند.
  2. دسته بندی آن را در DashboardFragmentRegistry تعریف کنید.

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

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

اعتبارسنجی

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