Architektura informacji

W systemie Android 8.0 wprowadzono nową architekturę informacji dla aplikacji Ustawienia, aby uprościć sposób organizacji ustawień i ułatwić użytkownikom szybkie znajdowanie ustawień w celu dostosowania ich urządzeń z Androidem. W systemie Android 9 wprowadzono pewne ulepszenia, aby zapewnić większą funkcjonalność Ustawień i łatwiejszą implementację.

Przykłady i źródło

Większość stron w Ustawieniach jest obecnie zaimplementowana przy użyciu nowego frameworka. Dobrym przykładem jest DisplaySettings: packages/apps/Settings/src/com/android/settings/DisplaySettings.java

Ścieżki plików ważnych komponentów są wymienione poniżej:

  • 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 (wprowadzony w systemie Android 9): packages/apps/Settings/src/com/android/settings/core/BasePreferenceController.java

Realizacja

Zachęcamy producentów urządzeń do dostosowania istniejącej architektury informacji o ustawieniach i wstawienia dodatkowych stron ustawień, jeśli jest to konieczne, aby uwzględnić funkcje specyficzne dla partnera. Przenoszenie preferencji ze starszej strony (zaimplementowanej jako SettingsPreferencePage ) na nową stronę (zaimplementowanej przy użyciu DashboardFragment ) może być skomplikowane. Preferencje ze starszej strony prawdopodobnie nie są zaimplementowane w PreferenceController .

Zatem podczas przenoszenia preferencji ze starszej strony na nową stronę należy utworzyć PreferenceController i przenieść kod do kontrolera przed utworzeniem jego instancji w nowym DashboardFragment . Interfejsy API wymagane przez PreferenceController są opisane w ich nazwach i udokumentowane w Javadoc.

Zdecydowanie zaleca się dodanie testu jednostkowego dla każdego PreferenceController . Jeśli zmiana zostanie zgłoszona do AOSP, wymagany jest test jednostkowy. Aby uzyskać więcej informacji na temat pisania testów opartych na Robolectric, zobacz packages/apps/Settings/tests/robotests/README.md .

Architektura informacji w stylu wtyczki

Każdy element ustawień jest zaimplementowany jako Preferencja. Preferencje można łatwo przenosić z jednej strony na drugą.

Aby ułatwić przenoszenie wielu ustawień, w systemie Android 8.0 wprowadzono fragment hosta w stylu wtyczki, który zawiera elementy ustawień. Elementy ustawień są modelowane jako kontrolery w stylu wtyczek. Dlatego strona ustawień jest zbudowana z pojedynczego fragmentu hosta i wielu kontrolerów ustawień.

Fragment panelu kontrolnego

DashboardFragment to host kontrolerów preferencji w stylu wtyczek. Fragment dziedziczy z PreferenceFragment i ma haki do rozwijania i aktualizowania zarówno statycznych, jak i dynamicznych list preferencji.

Preferencje statyczne

Statyczna lista preferencji jest definiowana w formacie XML przy użyciu znacznika <Preference> . Implementacja DashboardFragment wykorzystuje metodę getPreferenceScreenResId() do zdefiniowania, który plik XML zawiera statyczną listę preferencji do wyświetlenia.

Preferencje dynamiczne

Element dynamiczny reprezentuje kafelek z intencją, prowadzący do działania zewnętrznego lub wewnętrznego. Zwykle intencja prowadzi do innej strony ustawień. Na przykład element ustawień „Google” na stronie głównej Ustawień jest elementem dynamicznym. Elementy dynamiczne są zdefiniowane w AndroidManifest (omówione poniżej) i ładowane przez FeatureProvider (zdefiniowane jako DashboardFeatureProvider ).

Ustawienia dynamiczne mają większą wagę niż ustawienia skonfigurowane statycznie, dlatego zwykle programiści powinni zaimplementować to ustawienie jako statyczne. Jednak ustawienie dynamiczne może być przydatne, gdy spełniony jest którykolwiek z poniższych warunków:

  • To ustawienie nie jest bezpośrednio implementowane w aplikacji Ustawienia (np. poprzez wstrzykiwanie ustawień zaimplementowanych przez aplikacje OEM/operatora).
  • Ustawienie powinno pojawić się na stronie głównej Ustawień.
  • Masz już działanie dla tego ustawienia i nie chcesz implementować dodatkowej konfiguracji statycznej.

Aby skonfigurować działanie jako ustawienie dynamiczne, wykonaj następujące czynności:

  • Oznacz działanie jako ustawienie dynamiczne, dodając do działania filtr intencji.
  • Powiedz aplikacji Ustawienia, do której kategorii należy. Kategoria jest stałą zdefiniowaną w CategoryKey .
  • Opcjonalnie: Dodaj tekst podsumowania, gdy ustawienie jest wyświetlane.

Oto przykład wzięty z aplikacji Ustawienia dla 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>

W czasie renderowania fragment poprosi o listę preferencji zarówno ze statycznego XML, jak i ustawień dynamicznych zdefiniowanych w AndroidManifest . Niezależnie od tego, czy PreferenceController są zdefiniowane w kodzie Java, czy w formacie XML, DashboardFragment zarządza logiką obsługi każdego ustawienia za pomocą PreferenceController (omówione poniżej). Następnie są one wyświetlane w interfejsie użytkownika jako lista mieszana.

Kontroler preferencji

Istnieją różnice między implementacją PreferenceController w systemach Android 9 i Android 8.x, zgodnie z opisem w tej sekcji.

PreferenceController w wersji Androida 9

PreferenceController zawiera całą logikę interakcji z preferencjami, w tym wyświetlanie, aktualizowanie, indeksowanie wyszukiwania itp.

Interfejs PreferenceController jest zdefiniowany jako BasePreferenceController . Na przykład zobacz kod w packages/apps/Settings/src/com/android/settings/core/ BasePreferenceController.java

Istnieje kilka podklas BasePreferenceController , z których każda jest mapowana na określony styl interfejsu użytkownika, który domyślnie obsługuje aplikacja Ustawienia. Na przykład TogglePreferenceController ma interfejs API, który bezpośrednio odwzorowuje sposób, w jaki użytkownik powinien wchodzić w interakcję z interfejsem użytkownika opartym na przełączaniu.

BasePreferenceController posiada API takie jak getAvailabilityStatus() , displayPreference() , handlePreferenceTreeClicked(), itp. Szczegółowa dokumentacja każdego API znajduje się w klasie interfejsu.

Ograniczeniem implementacji BasePreferenceController (i jego podklas, takich jak TogglePreferenceController ) jest to, że podpis konstruktora musi odpowiadać jednemu z poniższych:

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

Podczas instalowania preferencji do fragmentu pulpit nawigacyjny udostępnia metodę dołączenia PreferenceController przed czasem wyświetlania. W czasie instalacji kontroler jest podłączony do fragmentu, dzięki czemu wszystkie przyszłe istotne zdarzenia są wysyłane do kontrolera.

DashboardFragment przechowuje listę PreferenceController na ekranie. W funkcji onCreate() fragmentu wywoływane są wszystkie kontrolery dla metody getAvailabilityStatus() i jeśli zwróci ona wartość true, wywoływana jest displayPreference() w celu przetworzenia logiki wyświetlania. getAvailabilityStatus() jest również ważna, aby poinformować strukturę ustawień, które elementy są dostępne podczas wyszukiwania.

PreferenceController w wersjach Androida 8.x

PreferenceController zawiera całą logikę interakcji z preferencjami, w tym wyświetlanie, aktualizowanie i indeksowanie wyszukiwania. itp.

Odpowiednio do interakcji preferencji interfejs PreferenceController posiada funkcje API isAvailable() , displayPreference() , handlePreferenceTreeClicked() itp. Szczegółową dokumentację każdego API można znaleźć w klasie interfejsu.

Podczas instalowania preferencji do fragmentu pulpit nawigacyjny udostępnia metodę dołączenia PreferenceController przed czasem wyświetlania. W czasie instalacji kontroler jest podłączony do fragmentu, dzięki czemu wszystkie przyszłe istotne zdarzenia są wysyłane do kontrolera.

DashboardFragment przechowuje listę PreferenceControllers na ekranie. W funkcji onCreate() fragmentu wywoływane są wszystkie kontrolery dla metody isAvailable() i jeśli zwróci ona wartość true, wywoływana jest displayPreference() w celu przetworzenia logiki wyświetlania.

Korzystanie z fragmentu pulpitu nawigacyjnego

Przenoszenie preferencji ze strony A na B

Jeśli preferencja jest statycznie wymieniona w pliku XML preferencji oryginalnej strony, wykonaj poniższą procedurę przenoszenia statycznego dla swojej wersji Androida. W przeciwnym razie wykonaj procedurę przenoszenia dynamicznego dla swojej wersji Androida.

Ruch statyczny w Androidzie 9

  1. Znajdź pliki XML preferencji dla strony oryginalnej i strony docelowej. Informacje te można znaleźć w metodzie getPreferenceScreenResId() strony.
  2. Usuń preferencje z kodu XML oryginalnej strony.
  3. Dodaj preferencje do kodu XML strony docelowej.
  4. Usuń PreferenceController dla tej preferencji z implementacji Java oryginalnej strony. Zwykle jest to createPreferenceControllers() . Kontroler można zadeklarować bezpośrednio w formacie XML.

    Uwaga : preferencja może nie mieć PreferenceController .

  5. Utwórz instancję PreferenceController w funkcji createPreferenceControllers() strony docelowej. Jeśli PreferenceController jest zdefiniowany w formacie XML na starej stronie, zdefiniuj go w formacie XML również dla nowej strony.

Dynamiczny ruch w Androidzie 9

  1. Znajdź kategorię, w której znajduje się strona oryginalna i docelowa. Informacje te można znaleźć w DashboardFragmentRegistry .
  2. Otwórz plik AndroidManifest.xml zawierający ustawienie, które chcesz przenieść, i znajdź wpis Działanie reprezentujący to ustawienie.
  3. Ustaw wartość metadanych działania dla com.android.settings.category na klucz kategorii nowej strony.

Ruch statyczny w wersjach Androida 8.x

  1. Znajdź pliki XML preferencji dla strony oryginalnej i strony docelowej.
  2. Informacje te można znaleźć w metodzie getPreferenceScreenResId() strony.
  3. Usuń preferencje z kodu XML oryginalnej strony.
  4. Dodaj preferencje do kodu XML strony docelowej.
  5. Usuń PreferenceController dla tej preferencji w implementacji Java oryginalnej strony. Zwykle jest to getPreferenceControllers() .
  6. Uwaga : Możliwe, że preferencja nie posiada PreferenceController .

  7. Utwórz instancję PreferenceController w metodzie getPreferenceControllers() strony docelowej.

Dynamiczny ruch w wersjach Androida 8.x

  1. Znajdź kategorię, w której znajduje się strona oryginalna i docelowa. Informacje te można znaleźć w DashboardFragmentRegistry .
  2. Otwórz plik AndroidManifest.xml zawierający ustawienie, które chcesz przenieść, i znajdź wpis Działanie reprezentujący to ustawienie.
  3. Zmień wartość metadanych działania dla com.android.settings.category , ustaw punkt wartości na klucz kategorii nowej strony.

Tworzenie nowych preferencji na stronie

Jeśli preferencja jest statycznie wymieniona w pliku XML preferencji oryginalnej strony, postępuj zgodnie z poniższą procedurą statyczną . W przeciwnym razie postępuj zgodnie z procedurą dynamiczną .

Tworzenie preferencji statycznych

  1. Znajdź pliki XML preferencji dla strony. Informacje te można znaleźć w metodzie getPreferenceScreenResId() strony.
  2. Dodaj nowy element preferencji w pliku XML. Upewnij się, że ma unikalny android:key .
  3. Zdefiniuj PreferenceController dla tej preferencji w metodzie getPreferenceControllers() strony.
    • W systemie Android 8.x i opcjonalnie w systemie Android 9 utwórz instancję PreferenceController dla tej preferencji w metodzie createPreferenceControllers() strony.

      Jeśli ta preferencja istniała już w innych miejscach, możliwe, że istnieje już dla niej PreferenceController . Możesz ponownie użyć PreferenceController bez tworzenia nowego.

    • Począwszy od systemu Android 9, obok preferencji możesz zadeklarować PreferenceController w formacie XML. Na przykład:
      <Preference
              android:key="reset_dashboard"
              android:title="@string/reset_dashboard_title"
              settings:controller="com.android.settings.system.ResetPreferenceController"/>
      

Tworzenie preferencji dynamicznych

  1. Znajdź kategorię, w której znajduje się strona oryginalna i docelowa. Informacje te można znaleźć w DashboardFragmentRegistry .
  2. Utwórz nowe działanie w AndroidManifest
  3. Dodaj niezbędne metadane do nowego działania, aby zdefiniować ustawienie. Ustaw wartość metadanych dla com.android.settings.category na tę samą wartość zdefiniowaną w kroku 1.

Utwórz nową stronę

  1. Utwórz nowy fragment, dziedzicząc z DashboardFragment .
  2. Zdefiniuj jego kategorię w DashboardFragmentRegistry .

    Uwaga: ten krok jest opcjonalny. Jeśli nie potrzebujesz żadnych dynamicznych preferencji na tej stronie, nie musisz podawać klucza kategorii.

  3. Postępuj zgodnie z instrukcjami dodawania ustawień potrzebnych dla tej strony. Więcej informacji znajdziesz w dziale Implementacja .

Walidacja

  • Uruchom testy robotyczne w Ustawieniach. Wszystkie istniejące i nowe testy powinny przejść pomyślnie.
  • Zbuduj i zainstaluj Ustawienia, a następnie ręcznie otwórz modyfikowaną stronę. Strona powinna zostać natychmiast zaktualizowana.