Obsługa zmian konfiguracji

Niektóre konfiguracje urządzeń mogą się zmieniać podczas działania aplikacji. Są to między innymi: ale nie tylko:

  • Rozmiar wyświetlanej aplikacji
  • Orientacja ekranu
  • Rozmiar i waga czcionki
  • Język
  • Tryb ciemny a tryb jasny
  • Dostępność klawiatury

Większość zmian w konfiguracji jest wynikiem interakcji użytkownika. Dla: Na przykład obrót lub złożenie urządzenia zmienia ilość miejsca na ekranie dostępnych w Twojej aplikacji. Podobnie zmiana ustawień urządzenia, takich jak rozmiar czcionki, język lub preferowany motyw zmienia odpowiednie wartości w sekcji Configuration.

Te parametry wymagają zwykle wystarczająco dużych zmian w interfejsie aplikacji które platforma Androida ma specjalnie opracowany mechanizm w razie zmian. Ten mechanizm to Activity odtworzenie.

Rekreacja

System odtwarza Activity po zmianie konfiguracji. W tym celu system wywołuje onDestroy() i niszczy istniejącą instancję Activity. Następnie tworzy nową instancję przy użyciu onCreate(), a ta nowa instancja Activity jest zainicjowano z nową, zaktualizowaną konfiguracją. Oznacza to również, że system odtworzy także interfejs użytkownika z nową konfiguracją.

Odtwarzanie pozwala dostosować aplikację do nowych konfiguracji przez: automatyczne ponowne wczytywanie aplikacji przy użyciu alternatywnych zasobów nową konfigurację urządzenia.

Przykład rekreacyjny

Weźmy pod uwagę element TextView, który wyświetla statyczny tytuł w postaci nazwy android:text="@string/title" zgodnie z definicją w pliku XML układu. Po wyświetleniu gdy zostanie utworzony, tekst zostanie ustawiony dokładnie raz, zależnie od języka bieżącego. Jeśli zmiany języka, system odtworzy aktywność. W związku z tym system również odtwarza widok i inicjuje go do prawidłowej wartości na podstawie nowego parametru język.

Odtwarzanie powoduje też wyczyszczenie wszystkich stanów przechowywanych jako pola w Activity ani w żadnym z jego zawartych w nim obiektów Fragment, View lub innych. Ten jest to, że odtworzenie typu Activity tworzy zupełnie nową instancję Activity i interfejsie. Ponadto stary Activity nie jest już widoczny ani ważny, więc pozostałe odwołania do niego lub do jego obiektów znajdujących się w nim są nieaktualne. Mogą powodować, oraz wycieku pamięci i awarii.

Oczekiwania użytkowników

Użytkownik aplikacji oczekuje, że stan zostanie zachowany. Jeśli użytkownik wypełnia formularz i otwiera inną aplikację w trybie wielu okien, by odwołać się do informacji, pogarsza wrażenia użytkownika, jeśli wraca do prawidłowo wypełnionego formularza lub w innym miejscu w aplikacji. Jako deweloper musisz zapewnić spójne wrażenia użytkowników przez zmiany konfiguracji i odtwarzanie aktywności.

Aby sprawdzić, czy stan w aplikacji został zachowywany, możesz wykonać te czynności: działania, które powodują zmianę konfiguracji zarówno wtedy, gdy aplikacja działa na pierwszym planie, gdy jest w tle. Dotyczy to następujących czynności:

  • Obracanie urządzenia
  • Uruchamiam tryb wielu okien
  • Zmiana rozmiaru aplikacji w trybie wielu okien lub w oknie dowolnym
  • Składanie urządzenia składanego z kilkoma wyświetlaczami
  • zmiana motywu systemowego, np. tryb ciemny lub jasny;
  • Zmiana rozmiaru czcionki
  • Zmienianie języka systemu lub aplikacji
  • Podłączanie i odłączanie klawiatury sprzętowej
  • Podłączanie i odłączanie stacji dokującej
.

Istnieją 3 główne sposoby utrzymania odpowiedniego stanu Activity odtworzenie. Wybór zależy od rodzaju stanu, który chcesz zachowaj:

  • Lokalna trwałość niezbędna do obsługi śmierci procesu w przypadku złożonych lub dużych danych. Trwała pamięć lokalna obejmuje bazy danych lub DataStore.
  • Przechowywane obiekty, takie jak instancje ViewModel, do obsługi stanu związanego z interfejsem użytkownika w gdy użytkownik aktywnie korzysta z aplikacji.
  • Zapisano stan instancji, aby obsługiwać zainicjowane przez system śmierć procesu i zachowywać stan przejściowy, który zależy od danych wejściowych użytkownika lub nawigacji.

Aby dowiedzieć się więcej o interfejsach API każdego z nich, a jeśli używa się każdego z nich, przeczytaj sekcję Zapisywanie stanów interfejsu.

Ogranicz odtwarzanie aktywności

Możesz zapobiec automatycznemu odtwarzaniu aktywności w przypadku określonych zmian w konfiguracji. Odtworzenie Activity powoduje odtworzenie całego interfejsu użytkownika i wszystkich utworzonych obiektów z Activity. Możesz mieć ważne powody, aby tego uniknąć. Dla: na przykład aplikacja nie musi aktualizować zasobów w określonym czasie w konfiguracji serwera lub usługi. W takim przypadku możesz zadeklarować, że Twoja aktywność obsługuje zmianę samej konfiguracji, uniemożliwiają systemowi ponowne uruchomienie aktywności.

Aby wyłączyć odtwarzanie aktywności dla określonych zmian konfiguracji, dodaj typ konfiguracji do android:configChanges w <activity> w pliku AndroidManifest.xml. Możliwe wartości są widoczne w dokumentację atrybutu android:configChanges.

Ten kod manifestu wyłącza odtwarzanie Activity dla MyActivity, gdy orientacja ekranu i dostępność klawiatury:

<activity
    android:name=".MyActivity"
    android:configChanges="orientation|screenSize|screenLayout|keyboardHidden"
    android:label="@string/app_name">

Niektóre zmiany w konfiguracji zawsze powodują ponowne uruchomienie aktywności. Nie można wyłączyć . Nie możesz na przykład wyłączyć dynamicznej zmiany kolorów. wprowadzone w Androidzie 12L (poziom API 32).

Reagowanie na zmiany konfiguracji w systemie widoku danych

W systemie View, gdy nastąpi zmiana konfiguracji, której wyłączone odtwarzanie Activity, aktywność otrzyma wywołanie Activity.onConfigurationChanged(). Każdy dołączony widok otrzymuje również pod numer View.onConfigurationChanged(). W przypadku zmian konfiguracji nie dodano do android:configChanges, system odtwarza aktywność jak zwykle.

Metoda wywołania zwrotnego onConfigurationChanged() otrzymuje Obiekt Configuration, który określa nową konfigurację urządzenia. Odczytano pól w obiekcie Configuration, aby określić, Aby wprowadzić kolejne zmiany, zaktualizuj zasoby używanych w interfejsie. Gdy system wywoła tę metodę, aktywność Obiekt Resources został zaktualizowany, aby zwracać zasoby na podstawie nowego konfiguracji. Umożliwia resetowanie elementów interfejsu użytkownika bez korzystania z systemu ponowne uruchomienie aktywności.

Na przykład te testy implementacji onConfigurationChanged() czy klawiatura jest dostępna:

Kotlin

override fun onConfigurationChanged(newConfig: Configuration) {
    super.onConfigurationChanged(newConfig)

    // Checks whether a keyboard is available
    if (newConfig.keyboardHidden === Configuration.KEYBOARDHIDDEN_YES) {
        Toast.makeText(this, "Keyboard available", Toast.LENGTH_SHORT).show()
    } else if (newConfig.keyboardHidden === Configuration.KEYBOARDHIDDEN_NO) {
        Toast.makeText(this, "No keyboard", Toast.LENGTH_SHORT).show()
    }
}

Java

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);

    // Checks whether a keyboard is available
    if (newConfig.keyboardHidden == Configuration.KEYBOARDHIDDEN_YES) {
        Toast.makeText(this, "Keyboard available", Toast.LENGTH_SHORT).show();
    } else if (newConfig.keyboardHidden == Configuration.KEYBOARDHIDDEN_NO){
        Toast.makeText(this, "No keyboard", Toast.LENGTH_SHORT).show();
    }
}

Jeśli nie musisz aktualizować aplikacji na podstawie tych konfiguracji zmian, nie możesz zaimplementować onConfigurationChanged(). Pod tym kątem wszystkie zasoby używane przed zmianą konfiguracji są nadal używane, udało Ci się tylko uniknąć ponownego rozpoczęcia aktywności. Na przykład aplikacja TV może nie reagować, gdy klawiatura Bluetooth jest podłączona lub odłączona.

Zachowaj stan

Korzystając z tej techniki, musisz zachować stan w czasie cyklu życia aktywności. Dzieje się tak, ponieważ:

  • Zmiany nieuniknione: zmiany w konfiguracji, których nie możesz zapobiec, mogą ponownie uruchomić aplikację.
  • Proces kończenia się procesem: aplikacja musi być w stanie obsługiwać inicjowane przez system śmierć procesu. Jeśli użytkownik opuści aplikację i przejdzie ona do sekcji system może zniszczyć tę aplikację.
.

Reagowanie na zmiany konfiguracji w Jetpack Compose

Jetpack Compose ułatwia reagowanie na zmiany w konfiguracji aplikacji. Jeśli jednak wyłączysz odtwarzanie Activity dla wszystkich zmian konfiguracji, w których jest to możliwe, aplikacja wciąż musi poprawnie zmian konfiguracji.

Obiekt Configuration jest dostępny w hierarchii UI tworzenia wiadomości za pomocą lokalnej kompozycji LocalConfiguration. Gdy tylko się zmieni, funkcje kompozycyjne odczytujące dane z pola LocalConfiguration.current powodują ponowne komponowanie. Dla: informacje o działaniu lokalnych kompozycji znajdziesz w artykule Ograniczone lokalnie za pomocą CompositionLocal.

Przykład

W przykładzie poniżej funkcja kompozycyjna wyświetla datę w określonym formacie. Funkcja kompozycyjna reaguje na zmiany ustawień regionalnych systemu, wywołując ConfigurationCompat.getLocales() z: LocalConfiguration.current.

@Composable
fun DateText(year: Int, dayOfYear: Int) {
    val dateTimeFormatter = DateTimeFormatter.ofPattern(
        "MMM dd",
        ConfigurationCompat.getLocales(LocalConfiguration.current)[0]
    )
    Text(
        dateTimeFormatter.format(LocalDate.ofYearDay(year, dayOfYear))
    )
}

Aby uniknąć odtworzenia Activity w przypadku zmiany regionu, Activity hostujący Kod tworzenia musi zrezygnować ze zmian konfiguracji języka. W tym celu ustaw android:configChanges na locale|layoutDirection.

Zmiany w konfiguracji: kluczowe pojęcia i sprawdzone metody

Oto kluczowe pojęcia, które musisz znać podczas pracy nad konfiguracją zmiany:

  • Konfiguracje:konfiguracje urządzeń określają, jak interfejs użytkownika jest wyświetlany użytkownika, np. rozmiar interfejsu aplikacji, język lub motyw systemu.
  • Zmiany konfiguracji: konfiguracja zmienia się w wyniku interakcji użytkownika. Dla: np. zmienić ustawienia urządzenia lub sposób interakcji, z urządzeniem. Nie ma sposobu na zapobieganie zmian konfiguracji.
  • Activity odtworzenie: zmiany konfiguracji skutkują odtworzeniem Activity razy domyślnie. To wbudowany mechanizm ponownego inicjowania stanu aplikacji nową konfigurację.
  • Zniszczenia Activity: odtworzenie Activity powoduje zniszczenie systemu stara instancję Activity, a w jej miejsce utworzyć nową. Stara instancja to przestarzały. Wszelkie pozostałe odwołania do niego mogą spowodować wycieki pamięci, lub awarii.
  • Stan: stan w starej instancji Activity nie występuje w nowym Activity, ponieważ są to 2 różne instancje obiektów. Zachowaj aplikacji i stanu użytkownika, zgodnie z opisem w sekcji Zapisywanie stanów interfejsu użytkownika.
  • Opcja rezygnacji: rezygnacja z odtwarzania aktywności w przypadku określonego typu konfiguracji. jest potencjalna optymalizacja. Wymagana jest aplikacja aktualizuje się odpowiednio do nowej konfiguracji.

Aby zadbać o wygodę użytkowników, stosuj te sprawdzone metody:

  • Przygotuj się na częste zmiany konfiguracji: nie zakładaj, że zmiany w konfiguracji jest rzadki lub nigdy nie występuje, niezależnie od poziomu interfejsu API, formatu czy zestawu narzędzi UI. Gdy użytkownik wprowadza zmianę konfiguracji, oczekuje, że aplikacje zostaną zaktualizowane będzie nadal działać prawidłowo z nową konfiguracją.
  • Zachowaj stan: nie utracisz stanu użytkownika, gdy zostanie odtworzone Activity. ma miejsce. Zachowaj stan w sposób opisany w artykule Zapisywanie stanów interfejsu.
  • Aby szybko zrezygnować z rezygnowania, nie rezygnuj z odtwarzania Activity. jako skrótu do uniknięcia utraty stanu. Wymagania dotyczące rezygnacji z rekreacji Wywiązywanie się z obietnicy dotyczącej wprowadzenia zmian, a Użytkownik nadal może stan z powodu Activity odtworzenia z innych zmian konfiguracji, proces śmierci lub zamknięcia aplikacji. Nie można całkowicie wyłączyć funkcji Activity rekreacji. Zachowaj stan w sposób opisany w artykule Zapisywanie stanów interfejsu.
  • Nie unikaj zmian w konfiguracji: nie ograniczaj orientacji, format obrazu czy możliwość zmiany rozmiaru, Activity odtworzenie. Będzie to miało negatywny wpływ na użytkowników, którzy chcą korzystać z Twojej aplikacji w sposób, który najbardziej im odpowiada.

Obsługuj zmiany konfiguracji oparte na rozmiarze

Zmiany w konfiguracji na podstawie rozmiaru mogą wystąpić w dowolnym momencie, a ich prawdopodobieństwo jest większe. gdy aplikacja działa na dużym ekranie, na którym użytkownicy mogą trybie wielu okien. Oczekują, że aplikacja będzie dobrze działać dla środowiska.

Istnieją 2 ogólne typy zmian rozmiaru: istotne i nieistotne. Znaczna zmiana rozmiaru oznacza sytuacja, w której różne zasobów alternatywnych do nowej konfiguracji ze względu na różnicę w rozmiaru ekranu, np. szerokości, wysokości lub najmniejszej szerokości. Znajdziesz tam: zdefiniowane przez aplikację oraz te z jej bibliotek.

Ogranicz odtwarzanie aktywności w przypadku zmian konfiguracji na podstawie rozmiaru

Jeśli wyłączysz odtwarzanie Activity w przypadku zmian konfiguracji na podstawie rozmiaru, system nie utworzy elementu Activity. Zamiast tego otrzymuje wywołanie Activity.onConfigurationChanged() Każdy dołączony widok otrzymuje wywołanie do View.onConfigurationChanged()

Odtwarzanie Activity jest wyłączone w przypadku zmian konfiguracji na podstawie rozmiaru, gdy: masz android:configChanges="screenSize|smallestScreenSize|orientation|screenLayout" w pliku manifestu.

Zezwalaj na odtwarzanie aktywności na potrzeby zmian konfiguracji na podstawie rozmiaru

W Androidzie 7.0 (poziom interfejsu API 24) i nowszych odtwarzanie Activity odbywa się tylko w przypadku aplikacji opartych na rozmiarze konfiguracji zmienia się, jeśli rozmiar jest istotny. Gdy system ponownie utworzyć Activity z powodu niewystarczającego rozmiaru, system może wywołać Activity.onConfigurationChanged() i View.onConfigurationChanged().

Pamiętaj o zastrzeżeniach dotyczących tych zasad: Activity i View. wywołania zwrotne, gdy Activity nie zostanie odtworzony:

  • Na Androidzie 11 (poziom interfejsu API 30) do 13 (poziom API 33) Urządzenie Activity.onConfigurationChanged() nie jest wywoływane.
  • Występuje znany problem, w przypadku którego usługa View.onConfigurationChanged() może nie być w niektórych przypadkach wywoływane na Androidzie 12L (poziom interfejsu API 32) i wczesnych wersjach Android 13 (poziom API 33). Więcej informacji znajdziesz w tym problemie publicznym. Ten problem został już rozwiązany w późniejszych wersjach Androida 13 i 14.

W przypadku kodu zależnego od nasłuchiwania konfiguracji opartej na rozmiarze zmian, zalecamy użycie narzędzia View z zastąpieniem View.onConfigurationChanged(), zamiast polegać na odtworzeniu Activity lub Activity.onConfigurationChanged()