Wprowadzenie do działań

Klasa Activity jest kluczowym komponentem aplikacji na Androida, a sposób uruchamiania i łączenia aktywności jest podstawową częścią modelu aplikacji na tej platformie. W odróżnieniu od paradygmatów programowania, w których aplikacje są uruchamiane za pomocą metody main, system Android inicjuje kod w instancji Activity, wywołując określone metody wywołania zwrotnego, które odpowiadają poszczególnym etapom cyklu życia.

W tym dokumencie przedstawiamy koncepcję działań, a następnie podajemy kilka prostych wskazówek dotyczących pracy z nimi. Więcej informacji o sprawdzonych metodach projektowania aplikacji znajdziesz w przewodniku po architekturze aplikacji.

Pojęcie aktywności

Aplikacja mobilna różni się od wersji na komputery tym, że interakcja użytkownika z aplikacją nie zawsze zaczyna się w tym samym miejscu. Zamiast tego ścieżka użytkownika często zaczyna się w sposób niedeterministyczny. Jeśli na przykład otworzysz aplikację do poczty e-mail z ekranu głównego, może się wyświetlić lista e-maili. Jeśli natomiast używasz aplikacji społecznościowej, która uruchamia aplikację do poczty e-mail, możesz przejść bezpośrednio do ekranu aplikacji do poczty e-mail, aby utworzyć e-maila.

Klasa Activity została zaprojektowana, aby ułatwić to podejście. Gdy jedna aplikacja wywołuje inną, wywołuje w niej działanie, a nie całą aplikację. W ten sposób aktywność służy jako punkt wejścia do interakcji aplikacji z użytkownikiem. Aktywność implementujesz jako podklasę klasy Activity.

Aktywność to okno, w którym aplikacja rysuje interfejs. Zwykle to okno wypełnia ekran, ale może być mniejsze i wyświetlać się nad innymi oknami.

Zazwyczaj jedno działanie w aplikacji jest określane jako działanie główne, czyli pierwszy ekran, który pojawia się po uruchomieniu aplikacji przez użytkownika. W nowoczesnych aplikacjach opartych na Compose jest to jedyne niezbędne działanie, ponieważ zawiera ono funkcje kompozycyjne w architekturze z jednym działaniem, a nie hierarchię widoków. Zamiast wielu aktywności aplikacji dla ekranów, komponenty kompozycyjne w aktywności hosta zawierają wiele miejsc docelowych nawigacji.

Aby używać aktywności w aplikacji, musisz zarejestrować informacje o nich w pliku manifestu aplikacji. Warto też znać cykle życia aktywności. W dalszej części tego dokumentu znajdziesz więcej informacji na te tematy.

Konfigurowanie pliku manifestu

Aby aplikacja mogła korzystać z aktywności, musisz zadeklarować je i niektóre ich atrybuty w pliku manifestu.

Zadeklaruj aktywności

Aby zadeklarować aktywność, otwórz plik manifestu i dodaj element <activity> jako element podrzędny elementu <application>. Przykład:

<manifest ... >
  <application ... >
      <activity android:name=".ExampleActivity" />
      ...
  </application ... >
  ...
</manifest >

Jedynym wymaganym atrybutem tego elementu jest android:name, który określa nazwę klasy działania. Możesz też dodać atrybuty, które określają cechy aktywności, takie jak etykieta, ikona lub motyw interfejsu. Więcej informacji o tych i innych atrybutach znajdziesz w dokumentacji referencyjnej elementu <activity>.

Deklarowanie filtrów intencji

Filtry intencji to bardzo przydatna funkcja platformy Android. Umożliwiają one uruchamianie aktywności nie tylko na podstawie wyraźnej prośby, ale też domniemanej. Na przykład wyraźna prośba może nakazać systemowi „Uruchom aktywność Wyślij e-mail w aplikacji Gmail”. Z kolei żądanie niejawne mówi systemowi: „Uruchom ekran wysyłania e-maila w dowolnej aktywności, która może to zrobić”. Gdy interfejs systemu pyta użytkownika, której aplikacji ma użyć do wykonania zadania, oznacza to, że działa filtr intencji.

Aby skorzystać z tej funkcji, zadeklaruj atrybut <intent-filter> w elemencie <activity>. Definicja tego elementu zawiera element <action> oraz opcjonalnie element <category> lub element <data>. Te elementy określają typ intencji, na którą może odpowiadać Twoja aktywność. Na przykład ten fragment kodu pokazuje, jak skonfigurować działanie, które wysyła dane tekstowe i e-maile oraz odbiera żądania od innych działań:

<activity android:name=".ExampleActivity" android:icon="@drawable/app_icon">
    <intent-filter>
        <action android:name="android.intent.action.SEND" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:mimeType="text/plain" />
    </intent-filter>
   <intent-filter>
        <action android:name="android.intent.action.SENDTO" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:scheme="mailto" />
    </intent-filter>
</activity>

W tym przykładzie element <action> określa, że to działanie wysyła dane. Zadeklarowanie elementu <category> jako DEFAULT umożliwia aktywności odbieranie próśb o uruchomienie. Element <data> określa typ danych, które to działanie może wysyłać. Poniższy fragment kodu pokazuje, jak wywołać opisaną powyżej aktywność, aby utworzyć e-maila:

fun composeEmail(addresses: Array<String>, subject: String) {
    val intent = Intent(Intent.ACTION_SENDTO).apply {
        data = Uri.parse("mailto:") // Only email apps handle this.
        putExtra(Intent.EXTRA_EMAIL, addresses)
        putExtra(Intent.EXTRA_SUBJECT, subject)
    }
    if (intent.resolveActivity(packageManager) != null) {
        startActivity(intent)
    }
}

Jeśli chcesz, aby aplikacja była samodzielna i nie zezwalała innym aplikacjom na aktywowanie jej działań, nie potrzebujesz żadnych innych filtrów intencji. Działania, które nie mają być dostępne dla innych aplikacji, nie powinny mieć filtrów intencji. Możesz je uruchamiać samodzielnie za pomocą jawnych intencji. Więcej informacji o tym, jak aktywności mogą reagować na intencje, znajdziesz w artykule Intencje i filtry intencji.

Obsługa przychodzących intencji

W tym przykładzie pokazano wzorzec zarządzania cyklem życia działania podczas obsługi wielu typów intencji: pojedynczych udostępnień tekstu, pojedynczych obrazów i tablic z wieloma obrazami. Przekierowując te różne dane wejściowe przez scentralizowaną handleIntentfunkcję, zapewnia, że działania ACTION_SENDACTION_SEND_MULTIPLE są prawidłowo analizowane i przekazywane do ViewModel w celu reaktywnej aktualizacji interfejsu.

class ExampleActivity : ComponentActivity() {
  private val viewModel: MyViewModel by viewModels()

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    handleIntent(intent)
    setContent {
      ComposeApp(viewModel)
    }
  }

  override fun onNewIntent(intent: Intent) {
    super.onNewIntent(intent)
    setIntent(intent)
    handleIntent(intent)
  }

  private fun handleIntent(intent: Intent?) {
    when (intent?.action) {
      Intent.ACTION_SEND -> {
        if ("text/plain" == intent.type) {
          intent.getStringExtra(Intent.EXTRA_TEXT)?.let {
            viewModel.handleText(it) // Update UI to reflect text being shared
          }
        } else if (intent.type?.startsWith("image/") == true) {
          (intent.getParcelableExtra(Intent.EXTRA_STREAM, Uri::class.java))?.let {
            viewModel.handleImage(it) // Update UI to reflect image being shared
          }
        }
      }

      Intent.ACTION_SEND_MULTIPLE -> {
          if (intent.type?.startsWith("image/") == true) {
              intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM, Uri::class.java)?.let {
                  viewModel.handleMultipleImages(it) // Update UI to reflect multiple images being shared
              }
          } else {
              // Handle other types
          }
      }

      else -> {
          // Handle other intents
      }
    }
  }
}

Deklarowanie uprawnień

Za pomocą tagu <activity> w pliku manifestu możesz określić, które aplikacje mogą uruchamiać konkretne działanie. Aktywność nadrzędna nie może uruchomić aktywności podrzędnej, chyba że obie aktywności mają w pliku manifestu te same uprawnienia. Jeśli zadeklarujesz element <uses-permission> dla działania nadrzędnego, każde działanie podrzędne musi mieć pasujący element <uses-permission>.

Jeśli na przykład Twoja aplikacja chce użyć hipotetycznej aplikacji o nazwie SocialApp do udostępniania postów w mediach społecznościowych, sama aplikacja SocialApp musi zdefiniować uprawnienia, które musi mieć aplikacja wywołująca ją:

<manifest>
<activity android:name="...."
   android:permission="com.google.socialapp.permission.SHARE_POST"

/>

Aby móc wywołać SocialApp, Twoja aplikacja musi mieć zbiór uprawnień zgodny z uprawnieniami w pliku manifestu SocialApp:

<manifest>
   <uses-permission android:name="com.google.socialapp.permission.SHARE_POST" />
</manifest>

Więcej informacji o uprawnieniach i zabezpieczeniach znajdziesz na liście kontrolnej dotyczącej bezpieczeństwa.

Zarządzanie cyklem życia działania

W trakcie swojego istnienia aktywność przechodzi przez kilka stanów. Do obsługi przejść między stanami używasz serii wywołań zwrotnych. W kolejnych sekcjach przedstawiamy te wywołania zwrotne. W aplikacji Compose nie zalecamy bezpośredniego podłączania się do tych wywołań zwrotnych. Zamiast tego używaj interfejsu Lifecycle API do obserwowania zmian stanu. Więcej informacji znajdziesz w artykule Integracja cyklu życia z Compose.

onCreate

Musisz zaimplementować to wywołanie zwrotne, które jest uruchamiane, gdy system tworzy Twoją aktywność. Implementacja powinna inicjować podstawowe komponenty aktywności. Na przykład aplikacja powinna tworzyć widoki i wiązać dane z listami.

W aplikacji Compose użyj tego wywołania zwrotnego, aby skonfigurować kompozycję hosta za pomocą funkcji setContent, jak pokazano poniżej:

class MyActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            Text(text = stringResource(id = R.string.greeting))
        }
    }
}

Gdy funkcja onCreate zakończy działanie, następne wywołanie zwrotne to zawsze onStart.

onStart

Gdy onCreate zostanie zamknięta, aktywność przejdzie w stan rozpoczęcia i będzie widoczna dla użytkownika. To wywołanie zwrotne zawiera ostateczne przygotowania aktywności do przejścia na pierwszy plan i umożliwienia interakcji.

onResume

System wywołuje to wywołanie zwrotne tuż przed rozpoczęciem interakcji aktywności z użytkownikiem. W tym momencie aktywność znajduje się na szczycie stosu działań i przechwytuje wszystkie dane wejściowe użytkownika. Większość głównej funkcjonalności aplikacji jest zaimplementowana w metodzie onResume.

Wywołanie zwrotne onPause zawsze następuje po wywołaniu onResume.

onPause

Gdy aktywność traci fokus i przechodzi w stan wstrzymania, system wywołuje metodę onPause. Ten stan występuje np. wtedy, gdy użytkownik kliknie przycisk Wstecz lub Ostatnie. Gdy system wywołuje metodę onPause w przypadku Twojej aktywności, oznacza to, że jest ona jeszcze częściowo widoczna, ale najczęściej wskazuje, że użytkownik opuszcza aktywność, która wkrótce przejdzie w stan Stopped lub Resumed.

Aktywność w stanie Wstrzymano może nadal aktualizować interfejs, jeśli użytkownik oczekuje jego aktualizacji. Przykładem takiej aktywności może być ekran mapy nawigacyjnej lub odtwarzacz multimediów. Nawet jeśli takie działania stracą fokus, użytkownik oczekuje, że interfejs będzie nadal aktualizowany.

Nie używaj onPause do zapisywania danych aplikacji lub danych użytkownika, wykonywania połączeń sieciowych ani przeprowadzania transakcji w bazie danych. Więcej informacji o zapisywaniu danych znajdziesz w artykule Zapisywanie i przywracanie tymczasowego stanu interfejsu.

Gdy funkcja onPause zakończy działanie, następne wywołanie zwrotne to onStop lub onResume, w zależności od tego, co się stanie po przejściu aktywności w stan wstrzymania.

onStop

System wywołuje funkcję onStop, gdy aktywność nie jest już widoczna dla użytkownika. Może się tak zdarzyć, ponieważ działanie jest niszczone, rozpoczyna się nowe działanie lub istniejące działanie wchodzi w stan wznowienia i przykrywa zatrzymane działanie. W każdym z tych przypadków zatrzymana aktywność nie jest już w ogóle widoczna.

Następne wywołanie zwrotne, które wywołuje system, to onRestart, jeśli aktywność wraca, aby wejść w interakcję z użytkownikiem, lub onDestroy, jeśli ta aktywność jest całkowicie zamykana.

onRestart

System wywołuje to wywołanie zwrotne, gdy aktywność w stanie Stopped ma zostać ponownie uruchomiona. onRestart przywraca stan aktywności z momentu jej zatrzymania.

Po tym wywołaniu zawsze następuje wywołanie onStart.

onDestroy

System wywołuje to wywołanie zwrotne przed zniszczeniem aktywności.

Jest to ostatnie wywołanie zwrotne, które otrzymuje aktywność. onDestroy jest zwykle implementowana, aby zapewnić zwolnienie wszystkich zasobów aktywności, gdy aktywność lub proces, który ją zawiera, zostanie zniszczony.

Ta sekcja zawiera tylko wprowadzenie do tego tematu. Szczegółowe omówienie cyklu życia aktywności i wywołań zwrotnych znajdziesz w artykule Cykl życia aktywności.