오늘도 더 나은 코드를 작성하였습니까?

destinations 생성 본문

Android Jetpack Architecture/Navigation

destinations 생성

hik14 2021. 11. 15. 21:10

1.  Fragment destination

- navi editer 에서 New Destination 아이콘 을 클릭한 다음 Create new destination을 클릭

- New Android Component 대화상자가 표시되면 Fragment Destination를 생성

 

2.  DialogFragment destination

<?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/nav_graph">

...

<dialog
    android:id="@+id/my_dialog_fragment"
    android:name="androidx.navigation.myapp.MyDialogFragment">
    <!--dialog가 수신 받는 데이터-->
    <argument android:name="myarg" android:defaultValue="@null" />
        <!--dialog가 갈수 있는 destination-->
        <action
            android:id="@+id/myaction"
            app:destination="@+id/another_destination"/>
</dialog>

...

</navigation>

 

3.  Activity destination 

 

Activity destination을 만드는 방법은 Fragment destination을 만드는 방법과 비슷합니다.

하지만 Activity destination Attribute은 상당히 다릅다.

 

기본적으로  navigation component 는 NavController를 Activity 레이아웃에 연결하고, navi graph는 범위가 Activity로 지정됩니다. 사용자가 다른 Activity로 이동하면 현재 navi graph는 더 이상 범위에 포함되지 않습니다.

즉, Activity destination은  navi graph의 엔드포인트로 간주되어야 합니다.

 

Activity 대상을 추가하려면 정규화된 클래스 이름으로 대상 Activity를 지정합니다.

<?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>

위의 destination으로 이동하게된다면 이전 destination에서 아래 코드를 호출한것 과 같다. 

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

 

* 이동할 Activity(destination)이 컴파일시에 정해지지 않는 경우, 암시적 인텐트를 통해 이동해야 하는 경우

 

manifest 에서 activity의 intent-filter를 통해 Activity(destination)을 구조화 해야한다.

<?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>

 

<?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>

Activity(destination)은 manifest 에 있는 속성과 일치하는 action   data 속성으로 구성해야 합니다

 

1)

<action android:name="android.intent.action.VIEW" />

---->  app:action="android.intent.action.VIEW"

 

2)

      <data
                    android:host="example.com"
                    android:scheme="https" />

 

---->  app:data="https://example.com"

 

targetPackage를 현재 applicationId로 지정하면 기본 앱을 포함한 현재 애플리케이션으로 범위가 제한됩니다.

 

특정 앱을 대상으로 지정하려는 경우에도 이 메커니즘을 사용할 수 있습니다.

예를들어  com.example.android.another.app의 applicationId를 갖는 앱을 destination으로 정의합니다.

 

* 특정 앱의 Activity로 이동하려고 할 때 지정된 앱이 기기에 설치되지 않았거나, 일치하는 intent-filter로 앱의 매니페스트에 정의된 Activity가 대상 앱에 없으면 ActivityNotFoundException이 발생합니다.

 

 

* 동적 인수 전달하기

 

위에서는  destination 으로 이동하는 데 고정 URL을 사용했습니다. 추가 정보가 URL의 일부로 전송되는 동적 URL을 지원해야 할 수도 있습니다. 예를 들어 https://example.com?userId= 와 유사한 형식의 URL로 사용자 ID를 보내기도 합니다.

 

 data 속성 대신 dataPattern을 사용합니다. 그런 다음 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>
navController.navigate(
    R.id.localDestinationActivity,
    bundleOf("userId" to "someUser")
)

4.  Placeholder 

placeholder 를 사용하여 구현되지 않은 destination을 나타낼 수 있습니다.

자리표시자는 destination을 시각적으로 표현하는 역할을 합니다. 탐색 편집기에서 다른 destination과 마찬가지로 placeholder를 사용할 수 있습니다.

 

앱을 실행하기 전에 placeholder 클래스 속성을 기존 대상으로 변경해야 합니다.

자리표시자 때문에 컴파일 오류가 발생하지는 않지만 placeholder 대상으로 이동하려고 시도하면 앱에서 런타임 예외가 발생합니다.