아래는 코모스튜디오가 직접 만든 무료 앱이에요(한 번만 봐주세요 ^^)
Activity
최초 액티비티에서
- activity_garden 을 layout으로 설정하게 되면
GardenActivity.kt
class GardenActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView<ActivityGardenBinding>(this, R.layout.activity_garden)
}
}
NagGraph
R.layout.activity_garden 에서는
- 이후 연결되는 view들을 아래와 같이 관리할 navigaion을 지정한다.
- app:navGraph="@navigation/nav_garden"
R.layout.activity_garden.xml
<layout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
android:id="@+id/nav_host"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
//뒤로 가기 설정
app:defaultNavHost="true"
//navigaion 지정
app:navGraph="@navigation/nav_garden"/>
</FrameLayout>
</layout>
Navigation
Sunflower는 크게 3가지 View로 이루어져 있는데
이 뷰들이 위 navGraph로 연결되어 관리되는데, 이후에는 safe argument를 통해 뷰 아이템들의 id 등을 쉽게 가져와서 사용할 수 있다.
ViewPager
- GardenFragment
- 심은 식물을 담는 RecyclerView
- PlantListFragment(RecyclerView)
- 모든 식물을 보여주는 RecyclerView
- DetailFragment
- 선택된 식물의 정보와 담기 버튼
이 구조는 JetPack의 Navigation으로 정의가 된다.
app:startDestination=시작될 뷰를 ViewPager로 넣었으며
app:destination = 이동할 뷰를 DetailFragment로 넣었다.
nav_garden.xml
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
//첫 시작 지점
app:startDestination="@id/view_pager_fragment">
<fragment
android:id="@+id/view_pager_fragment"
tools:layout="@layout/fragment_view_pager">
<action
android:id="@+id/action_view_pager_fragment_to_plant_detail_fragment"
//navigate() 할 경우 이동할 View
app:destination="@id/plant_detail_fragment"
app:enterAnim="@anim/slide_in_right"
app:exitAnim="@anim/slide_out_left"
app:popEnterAnim="@anim/slide_in_left"
app:popExitAnim="@anim/slide_out_right" />
</fragment>
<fragment
android:id="@+id/plant_detail_fragment"
android:label="@string/plant_details_title"
tools:layout="@layout/fragment_plant_detail">
<action
android:id="@+id/action_plant_detail_fragment_to_gallery_fragment"
app:destination="@id/gallery_fragment"
app:enterAnim="@anim/slide_in_right"
app:exitAnim="@anim/slide_out_left"
app:popEnterAnim="@anim/slide_in_left"
app:popExitAnim="@anim/slide_out_right" />
<argument
android:name="plantId"
app:argType="string" />
</fragment>
이와 같이 정의를 하면 아래 그림처럼 그래프로 표시된다
아이템 클릭 navigate
PlantList에서 아이템 하나를 클릭할 경우
위 navigation에서 destination으로 등록된 곳으로 보내는데, navigate()를 사용해서 화면을 이동시킨다.
이때 Safe Argument를 사용한다.
- app:destination으로 등록하면,
- HomeViewPagerFragmentDirections처럼 뒤에 Directions 클래스가 생성되며
- Safe Argument를 담을 수 있는
- actionViewPagerFragmentToPlantDetailFragment 가 생성된다.
- argument를 HomeViewPagerFragmentDirections로 안전하게 담은 뒤 destination으로 이동한다.
PlantListFramgment.kt
class PlantViewHolder(
private val binding: ListItemPlantBinding
) : RecyclerView.ViewHolder(binding.root) {
init {
binding.setClickListener {
binding.plant?.let { plant ->
navigateToPlant(plant, it)
}
}
}
private fun navigateToPlant(
plant: Plant,
view: View
) {
val direction =
HomeViewPagerFragmentDirections.actionViewPagerFragmentToPlantDetailFragment(
plant.plantId
)
//app:destination 으로 등록 하면,
//HomeViewPagerFragmentDirections 처럼 뒤에 Directions 클래스가 생성되며
//safe argument 를 담을 수 있는
//actionViewPagerFragmentToPlantDetailFragment 가 생성된다.
//argument 를 HomeViewPagerFragmentDirections 로 안전하게 담은 뒤,
//destination 이동한다.
//이동이 된 뒤, DetailFragment 에서는 이를 arg by navArg() 로 받아 와서 사용한다.
view.findNavController().navigate(direction)
}
fun bind(item: Plant) {
binding.apply {
plant = item
executePendingBindings()
}
}
}
Detail Fragment 설정
navigate(direction)을 통해 Detail View로 이동 한 뒤,
안전하게 담아온 Safe argument는 아래와 같이 ktx navArgs()로 위임하여 받아 올 수 있다.
그리고, 받아온 plantId로 Db에서 해당 식물의 자료를 가져와서 상세(Detail) 뷰에서 사용할 View Model을 생성한다.
참고) ViewModel 주입하기는 이 링크 참조 [Sunflower 디비 보기] ViewModel 주입(초기화) 과정
PlantDetailFragment.kt
class PlantDetailFragment : Fragment() {
//navArgs()로 safe argument 가져오기
private val args: PlantDetailFragmentArgs by navArgs()
//ViewModel 주입
private val plantDetailViewModel: PlantDetailViewModel by viewModels {
InjectorUtils.providePlantDetailViewModelFactory(requireActivity(), args.plantId)
}
코틀린 코드는 아래와 같이 Java에서 getArgument()로 받아오는 코드와 동일 하지만, ktx를 이용하여 코드의 깔끔함과 안전함을 더 하게 되었다.
Java Code
arg = PlantDetailFragmentArgs.fromBundle(getArguments()).getPlantId();
Summary
여기까지 하면 앱 시작점과 View의 연결 그리고 이동에 대한 기본이 완성된다.
그리고, JetPack의 Navigation을 사용하면 위와 같이 깔끔하게 앱 내 뷰의 배치 및 이동 연결 관계를 정의할 수 있으며, Safe Argument를 통해 데이터도 쉽고 안전하게 주고받을 수 있다.
Android AAC JetPack Sunflower
이 글은 코모가 구글 안드로이드 Sunflower를 디비보기 한 것입니다.
' [안드로이드 공부] > 선플라워 디비보기' 카테고리의 다른 글
[Sunflower 디비보기] BindingAdapter로 View visible/gone (0) | 2020.07.30 |
---|---|
[Sunflower 디비보기] Detail View 에서 Garden 으로 아이템 담기 MVVM (0) | 2020.07.29 |
[Sunflower 디비보기] 데이터 바인딩으로 ImageView 에 Glide (0) | 2020.07.29 |
[Sunflower 디비보기] 데이터 바인딩과 HtmlCompat.fromhtml (0) | 2020.07.29 |
[Sunflower 디비보기] ViewModel 주입(초기화) 과정 (0) | 2020.07.28 |
모든 게시물은 코모스튜디오의 소유이며, 무단 복제 수정은 절대 불가입니다. |
퍼가실 경우 댓글과 블로그 주소를 남기고 해당 게시물에 출처를 명확히 밝히세요. |