Miejsca docelowe aktywności

Na wykresie nawigacyjnym miejsce docelowe może być aktywnością. Chociaż najlepiej mieć jedną aktywność w aplikacji, aplikacje często używają osobnych aktywności dla różnych komponentów lub ekranów w aplikacji. W takich przypadkach przydają się miejsca docelowe aktywności.

Compose i Kotlin DSL

Dodawanie miejsca docelowego aktywności do wykresu nawigacyjnego działa zasadniczo tak samo w przypadku tworzenia i używania DSL Kotlin z fragmentami. Dzieje się tak, ponieważ podczas przekazywania właściwości NavGraph do funkcji kompozycyjnej NavHost używasz tej samej funkcji lambda createGraph().

Więcej informacji znajdziesz w artykule Automatyczne tworzenie wykresu za pomocą języka DSL Kotlin.

Plik XML

Tworzenie miejsca docelowego aktywności przypomina tworzenie miejsca docelowego fragmentu. Charakter miejsca docelowego aktywności jest jednak zupełnie inny.

Domyślnie biblioteka nawigacji dołącza element NavController do układu Activity, a aktywny wykres nawigacyjny jest ograniczony do aktywnego obszaru Activity. Jeśli użytkownik przejdzie pod inny element (Activity), bieżący wykres nawigacyjny przestanie być uwzględniony w zakresie. Oznacza to, że miejsce docelowe Activity powinno być traktowane jako punkt końcowy na wykresie nawigacyjnym.

Aby dodać miejsce docelowe aktywności, określ miejsce docelowe Activity za pomocą jego pełnej i jednoznacznej nazwy klasy:

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/navigation_graph"
    app:startDestination="@id/simpleFragment">

    <activity
        android:id="@+id/sampleActivityDestination"
        android:name="com.example.android.navigation.activity.DestinationActivity"
        android:label="@string/sampleActivityTitle" />
</navigation>

Ten kod XML jest odpowiednikiem następującego wywołania funkcji startActivity():

Kotlin

startActivity(Intent(context, DestinationActivity::class.java))

Java

startActivity(new Intent(context, DestinationActivity.class));

W niektórych przypadkach takie podejście może być nieodpowiednie. Możesz na przykład nie mieć uzależnionej od klasy działania zależności czasu kompilacji lub ustawić poziom pośredni, który polega na przekazywaniu intencji pośredniej. Element intent-filter w wpisie o miejscu docelowym Activity w pliku manifestu określa strukturę miejsca docelowego Activity.

Przeanalizujmy na przykład ten plik manifestu:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.android.navigation.activity">
    <application>
        <activity android:name=".DestinationActivity">
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
                <data
                    android:host="example.com"
                    android:scheme="https" />
                <category android:name="android.intent.category.BROWSABLE" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>
    </application>
</manifest>

Odpowiednie miejsce docelowe Activity musi być skonfigurowane za pomocą atrybutów action i data pasujących do tych we wpisie manifestu:

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/navigation_graph"
    app:startDestination="@id/simpleFragment">
    <activity
        android:id="@+id/localDestinationActivity"
        android:label="@string/localActivityTitle"
        app:action="android.intent.action.VIEW"
        app:data="https://example.com"
        app:targetPackage="${applicationId}" />
</navigation>

Ustawienie zakresu targetPackage na bieżącą aplikację applicationId ogranicza zakres do bieżącej aplikacji, w tym aplikacji głównej.

Tego samego mechanizmu możesz używać w przypadkach, gdy stroną docelową ma być konkretna aplikacja. Ten przykład określa miejsce docelowe jako aplikację z właściwością applicationId o wartości com.example.android.another.app.

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/navigation_graph"
    app:startDestination="@id/simpleFragment">
    <activity
        android:id="@+id/localDestinationActivity"
        android:label="@string/localActivityTitle"
        app:action="android.intent.action.VIEW"
        app:data="https://example.com"
        app:targetPackage="com.example.android.another.app" />
</navigation>

Argumenty dynamiczne

W poprzednich przykładach do przechodzenia do miejsc docelowych używano stałych adresów URL. Może być też konieczna obsługa dynamicznych adresów URL, w których w ramach adresu URL przesyłane są dodatkowe informacje. Identyfikator użytkownika możesz na przykład wysyłać w adresie URL w formacie podobnym do https://example.com?userId=<actual user ID>.

W takim przypadku zamiast atrybutu data użyj dataPattern. Następnie możesz podać argumenty, które zostaną zastąpione nazwanymi symbolami zastępczymi w wartości dataPattern:

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/navigation_graph"
    app:startDestination="@id/simpleFragment">
    <activity
        android:id="@+id/localDestinationActivity"
        android:label="@string/localActivityTitle"
        app:action="android.intent.action.VIEW"
        app:dataPattern="https://example.com?userId={userId}"
        app:targetPackage="com.example.android.another.app">
        <argument
            android:name="userId"
            app:argType="string" />
    </activity>
</navigation>

W tym przykładzie możesz określić wartość userId za pomocą Safe Args lub Bundle:

Kotlin

navController.navigate(
    R.id.localDestinationActivity,
    bundleOf("userId" to "someUser")
)

Java

Bundle args = new Bundle();
args.putString("userId", "someUser");
navController.navigate(R.id.localDestinationActivity, args);

W tym przykładzie zastępuje się someUser wartością {userId} i tworzy wartość identyfikatora URI https://example.com?userId=someUser.