네비게이션 컴포넌트의 추가 기능인 Safe Args 를 이용하는것이 좋다. Type Safe 하게 데이터를 전달할 수 있게 도와주기 때문에 의도치 않은 실수를 줄일 수 있다.
프로젝트 build.gradle 에 새로운 classpath 를 더해야한다. 이를 통해 Safe Args 플러그인을 이용하겠다는 것을 명시한다.
buildscript {
repositories {
...
}
dependencies {
classpath "com.android.tools.build:gradle:7.0.3"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.0"
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:2.3.5"
}
}
그리고 앱 모듈에 플러그인을 추가한다.
plugins {
...
id 'androidx.navigation.safeargs'
}
네비게이션 컨트롤러에게 액션 아이디를 알려줘서 직접 프레그먼트를 옮겨다닐 수 있게 했던것 처럼, 컨트롤러에게 argument 를 전달함으로써 컨트롤러가 적절한 프레그먼트에 해당 argument 를 전달하게 한다.
이렇게 argument 를 전달할때 Directions 클래스가 사용된다. Safe-Args 플러그인을 호라성화 하면 안드로이드 스튜디오는 각각의 프레그먼트에 대해 Directions 을 생성한다.
Directions 클래스는 각각의 프레그먼트가 할당받은 네비게이션 액션에 대한 함수를 포함하고 있다. 이러한 함수들에 argument 로 우리가 보내고자하는 메시지를 전달하면 된다.
TwoFragment 에서 ThreeFragment 로 메시지를 전달
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<EditText
android:id="@+id/editText"
android:hint="please enter your email"
android:inputType="textEmailAddress"
android:autofillHints="emailAddress"
android:layout_width="match_parent"
android:layout_height="480dp"
android:gravity="center"
android:textSize="40sp" />
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="myButton"/>
</LinearLayout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<TextView
android:id="@+id/myText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/email_value"
android:textSize="40sp" />
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Go First"/>
</LinearLayout>
이러한 프레그먼트에 대해 네비게이션 그래프를 등록한다. 여기서 해당 프레그먼트가 어떤 argumet 를 받을 것인지 명시한다.
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/nav_graph"
app:startDestination="@id/oneFragment">
<fragment
android:id="@+id/twoFragment"
android:name="com.examle.test.TwoFragment"
android:label="TwoFragment" >
<action
android:id="@+id/toThreeFragment"
app:destination="@id/threeFragment" />
</fragment>
<fragment
android:id="@+id/threeFragment"
android:name="com.examle.test.ThreeFragment"
android:label="ThreeFragment">
<argument
android:name="message_email"
app:argType="string" />
</fragment>
</navigation>
그리고 프레그먼트 뷰를 구성할때 Directions 클래스를 이용한다.
class TwoFragment: Fragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.fragment_two, container, false)
val button = view.findViewById<Button>(R.id.button)
val editText = view.findViewById<EditText>(R.id.editText)
button.setOnClickListener {
val messageEmail = editText.text.toString()
val action = TwoFragmentDirections.toThreeFragment(messageEmail)
view.findNavController().navigate(action)
}
return view
}
}
class ThreeFragment: Fragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.fragment_three, container, false)
val message = ThreeFragmentArgs.fromBundle(requireArguments()).messageEmail
val text = view.findViewById<TextView>(R.id.myText)
text.text = message