일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- Flutter
- binding
- Coroutines
- LifeCycle
- Button
- textview
- DART
- activity
- 앱
- 안드로이드
- 앱바
- appbar
- android
- 테스트
- viewmodel
- livedata
- Kotlin
- scroll
- data
- CustomScrollView
- intent
- textfield
- Navigation
- Dialog
- TEST
- tabbar
- Compose
- drift
- ScrollView
- 계측
- Today
- Total
Study Record
[안드로이드] Navigation 을 이용한 Fragment 데이터 전달, Safe Arg 본문
😶 개요
Fragment 사이의 데이터 전달은 Bundle 을 이용한다. Bundle 을 사용하면 key, value 값으로 데이터를 저장하면 해당 Fragment 에서 argmnent 변수로 Bundle 객체를 참고할 수 있다.
Bundle 객체로 Fragment 로 데이터 전달하기
val bundle = Bundle().apply {
this.putInt("test1", 3)
this.putString("test2", "testtest")
}
StartFragment().apply {
arguments = bundle
}
전달받은 데이터 해당 Fragment 에서 확인하기
arguments?.getInt("test1")
arguments?.getString("test2")
하지만 Bundle 객체를 이용하는 방식은 Bundle 은 프래그먼트에 Bundle 객체를 설정하지 않는다면 null 값을 반환하거나 default 값으로 반환하여 잘못된 작동을 할 수 있다.
따라서 이러한 문제들을 앱을 실행하기 전 컴파일 단계에서 발견하기 쉽게 도와주는 것이 Safe Args plugin 이다.
😶 Safe Args 기본 환경 설정
build.gradle(Project) - plugins 앞에 선언한다.
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
google()
}
dependencies {
def nav_version = "2.6.0"
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
}
}
build.gradle(Moudle)
plugins {
...
id 'androidx.navigation.safeargs.kotlin'
}
Navigation graph 파일의 argument 선언을 해준다.
<fragment
android:id="@+id/gameWonFragment"
android:name="com.example.android.navigation.GameWonFragment"
android:label="fragment_game_won"
tools:layout="@layout/fragment_game_won" >
<action
android:id="@+id/action_gameWonFragment_to_gameFragment"
app:destination="@id/gameFragment" />
<argument
android:name="nameCorrect"
app:argType="integer"
android:defaultValue="2"/>
<argument
android:name="namCheck"
app:argType="boolean"
android:defaultValue="true"/>
</fragment>
app:argType 으로 쓸 수 있는 것은 "integer", "float", "long", "boolean", "string", "reference" 가 있다. android:name 속성으로 인자의 이름을 정해주고 android:defaultValue 로 기본값을 설정할 수 있다.
Navigation Graph 설정을 마친 후 ReBuild 를 하면 몇 개의 클래스가 생성된다.
Navigation Graph 에서 탐색 이동의 대상이 되는 프래그먼트에 "Directions" 라는 단어가 추가된 이름의 새로운 클래스가 생성된다.
또한, 해당 프래그먼트에 <argument> 가 있다면 "Args" 가 붙은 클래스가 생성된다.
😶 탐색하기
다음과 같이 Navigation Graph 파일(navigation xml 파일)이 startFragment 와 workFragment 가 있고 startFragment > workFragment 로 이동하며 workFragment 에는 workArg1 과 workArg2 의 이름을 갖는 인자가 있다고 가정한다.
<?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_test"
app:startDestination="@id/startFragment">
<fragment
android:id="@+id/startFragment"
android:name="com.example.test2.StartFragment"
android:label="StartFragment" >
<action
android:id="@+id/action_startFragment_to_workFragment"
app:destination="@id/workFragment" />
</fragment>
<fragment
android:id="@+id/workFragment"
android:name="com.example.test2.WorkFragment"
android:label="WorkFragment" >
<argument
android:name="workArg1"
app:argType="integer"
android:defaultValue="2"/>
<argument
android:name="workArg2"
app:argType="boolean"
android:defaultValue="true"/>
</fragment>
</navigation>
Navigation Graph 파일이 완성된 후 ReBuild 를 하면 (debug) 파일이 생긴다.
defug 관련 파일에는 위에서 설명한 탐색 대상이 되는 프래그먼트에는 Directions 가 붙은 프래그먼트와 workFragment 의 인자와 관련된 새로운 클래스들이 생성된 것을 볼 수 있다.
startFragment 에서 workFragment 로 탐색하는 코드는 StartFragmentDirections 클래스를 이용하면 된다. 버튼을 눌렀을 때 workFragment 로 넘어가는 예시 코드이다.
binding.workBtn.setOnClickListener {
it.findNavController()
.navigate(StartFragmentDirections.actionStartFragmentToWorkFragment(3, false))
}
actionStartFragmentToWorkFragment(workArg1, workArg2) 로 되어있는데 이렇게 함수형태로 값들을 전달하기 때문에 Bundle 객체를 직접 사용할 때보다 컴파일 단계에서 오류를 확인하기 쉽다.
😶 수신 Fragment 에서 인자 사용하기 (ex. WorkFragment)
수신 대상 Fragment 에서는 해당 프래그먼트의 이름에 "Args" 가 붙은 WorkFragmentArgs 클래스로 정의한 argument 를 가져올 수 있다.
val workArg : WorkFragmentArgs = WorkFragmentArgs.fromBundle(requireArguments())
workArg.workArg1
workArg.workArg2
😶 처음 시작 Fragment 에 인자를 전달해야 할 경우
프로그래밍 방식으로 Navigation Graph 를 따로 설정하면서 Bundle 객체를 전달한다. 주의해야 할 점은 xml 파일의 app:navGraph 속성을 지정하면 안 된다. (중복으로 실행되기 때문)
val args: Bundle = Bundle().apply {
putInt("testArg", 4)
}
navController.setGraph(R.navigation.graph, args)
args 로 넘겨주는 Bundle 객체는 navigation 의 탐색 시작 프래그먼트의 argument 로 사용된다.
예시)
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)
}
override fun onResume() {
super.onResume()
val args = Bundle().also {
it.putString("test", "like")
}
binding.mainFg.findNavController()
.setGraph(R.navigation.navigation_test, args)
}
}
+ argument 마다 default 값 다르게 하기
<action> 태그 안에 <argument> 태그로 수신 대상 프래그먼트의 인자 기본값을 다르게 설정할 수 있다.
<action android:id="@+id/startMyFragment"
app:destination="@+id/myFragment">
<argument
android:name="myArg"
app:argType="integer"
android:defaultValue="1" />
</action>
'안드로이드' 카테고리의 다른 글
[안드로이드] 암시적 인텐트(implicit intent) 사용해보기 (0) | 2023.06.27 |
---|---|
[안드로이드] Intent 살펴보기 (0) | 2023.06.27 |
[안드로이드] 앱바 Menu 추가하기 (+ Navigation) , drawer (0) | 2023.06.25 |
[안드로이드] Navigation (탐색) 살펴보기 (0) | 2023.06.25 |
[안드로이드] Fragment 살펴보기 (0) | 2023.06.22 |