Sunflower 프로젝트를 본격적으로 리뷰하기 앞서 어떤 기준으로 리뷰해야 하는지 고민이 되었습니다.
고민 끝에 레이아웃을 기준으로 해당 레이아웃과 관련 있는 기능을 위주로 리뷰하기로 하였습니다.
전체 Layout
- 전체 레이아웃을 위와 같이 구성되어 있습니다.
- 구조만 보고 파악했을 때는 대략적으로 아래와 같이 구성되어있을 것이라 생각하였습니다.
- activity_garden을 메인 Activity로 갖는다.
- 메인 Activity 에서 navigation을 이용한 fragment 전환이 이루어진다.
- RecyclerView와 같은 리스트 뷰를 사용한 3가지 아이템이 존재한다.
- list_item_garden_planting.xml
- list_item_photo.xml
- list_item_plant.xml
대략적으로 생각한 것들이며 메인 Activity 인 activity_garden.xml을 먼저 살펴보기로 하였습니다.
activity_garden.xml
<layout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/nav_host"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="@navigation/nav_garden" />
</layout>
- layout으로 쌓여 있는 것으로 보아 Data Binding을 사용하였음을 알 수 있습니다.
- gradle을 확인해보니 아래와 같이 dataBinding을 사용하고 있음을 확인하였습니다.
buildFeatures {
dataBinding = true
}
- FragmentContatinerView 를 사용하고 있습니다.
- 속성 navGraph에서 navigation의 nav_garden을 따르고 있음을 알 수 있습니다.
- 개념에 대해서 간단하게 짚고 넘어가겠습니다.
FragmentContainerView
안드로이드 developer 에 아래와 같이 나와있습니다.
- FragmentContainerView는 Fragments 용으로 특별히 설계된 사용자 정의된 레이아웃이다.
- Fragment Transactions 을 안정적으로 처리할 수 있도록 Fragment Layout 을 확장하며 Fragment 동작에 맞춰 조정할 수 있는 추가 기능도 제공한다.
navigation 을 살펴보겠습니다.
navigation
<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"
android:name="com.google.samples.apps.sunflower.HomeViewPagerFragment"
tools:layout="@layout/fragment_view_pager">
<action
android:id="@+id/action_view_pager_fragment_to_plant_detail_fragment"
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:name="com.google.samples.apps.sunflower.PlantDetailFragment"
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>
<fragment
android:id="@+id/gallery_fragment"
android:name="com.google.samples.apps.sunflower.GalleryFragment"
android:label="@string/plant_details_title"
tools:layout="@layout/fragment_gallery">
<argument
android:name="plantName"
app:argType="string" />
</fragment>
</navigation>
메인 소스에서 한번 더 살펴봐야할 것이라 생각이 되지만 지금 간단하게 훑어보고 지나가겠습니다.
간단하게 특징만 골라서 정리하면 아래와 같습니다.
이 navigation 의 첫 시작은 view_pager_fragment를 아이디로 갖는 fragment입니다.
각 fragment는 label을 가지고 있으면 해당 label 은 앱 바가 있을 경우 제목을 표시해줍니다.
(label을 표시해주는 NavigationUI 가 지원하는 상단 앱 바 유형은 1. Toolbar, 2. CollapsingToolbarLayout, 3. ActionBar이다.)
각 fragment의 특징을 정리해보겠습니다.
- view_pager_fragment
- HomeViewPagerFragment 클래스를 기반으로 작동한다.
- action을 취하면 plant_detail_fragment 아이디를 갖는 fragment로 이동한다.
- 이동 시 애니메이션을 각각 적용한다.
- enterAnim : action 수행 시 목적지 화면에 입장하는 애니메이션
- exitAnim : action 수행 시 현재 화면으로 입장하는 애니메이션
- popEnterAnim : 이전 화면으로 돌아갈 때 목적 화면에 대한 애니메이션
- popExitAnim : 이전 화면으로 돌아갈 때 종료되는 화면에 대한 애니메이션
- plant_detail_fragment
- PlantDetailFragment 클래스를 기반으로 작동한다.
- action 을 취하면 gallery_ragment 아이디를 갖는 fragment 로 이동한다.
- 이동 시 애니메이션을 각각 적용한다(위와 동일).
- argument : fragment 이동 시 데이터를 전달할 때 사용한다.
- plantId 이름으로 String 타입의 데이터
- gallery_fragment
- GalleryFragment 클래스를 기반으로 작동한다.
- argument
- plantName 이름으로 String 타입의 데이터
여기까지 navigation에 대해 간단하게 알아보았습니다.
위 fragment의 흐름에 대해서 어느 정도 눈에 보이기 시작했습니다.
이제 메인 Activity layout을 살펴보았고 이 layout을 보여주는 Activity를 살펴보겠습니다.
GardenActivity
package com.google.samples.apps.sunflower
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil.setContentView
import com.google.samples.apps.sunflower.databinding.ActivityGardenBinding
import dagger.hilt.android.AndroidEntryPoint
@AndroidEntryPoint
class GardenActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView<ActivityGardenBinding>(this, R.layout.activity_garden)
}
}
이 프로젝트에는 해당 액티비티 단 한개만 존재합니다.
또한 내부의 기능은 Container 역할을 수행하는 것을 확인할 수 있습니다.
중요한 특징을 아래와 같이 정리해보았습니다.
- setContentView에서 layout Binding을 타입으로 명시하였다.
- DI(의존성 주입)를 사용하기 위해 Hilt의 @AndroidEntryPoint 어노테이션을 사용하였다.
@AndroidEntryPoint란
- 해당 어노테이션을 설정한 클래스는 Android class lifecycle을 따르는 종속 container를 생성한다.
- @Inject 어노테이션을 사용하기 위해서 클래스에 설정해야한다.
여기서 Hilt에 대해 간단하게 알아보도록 하겠습니다.
Hilt
Hilt란 무엇인가
- DI(Dependencies Injection, 의존성 주입)를 관리하기 위한 DI Tool입니다.
왜 사용하는가
- DI를 사용하면 유지관리, 테스트에 용이한 아키텍처를 구성하는데 도움이 됩니다.
어떻게 사용하는가
- 각 속성과 역할에 맞는 어노테이션을 설정하여 사용한다.
각 어노테이션에 대한 설명은 아래를 참고하면 됩니다.
https://thkim-study.tistory.com/19
[Android] Hilt 의존성 주입(DI) gradle 버전, 각 어노테이션 설명
gradle.build(project) buildscript { ext.kotlin_version = '1.3.72' ext.hilt_version = '2.28-alpha' repositories { google() jcenter() } dependencies { classpath 'com.android.tools.build:gradle:4.0.0'..
thkim-study.tistory.com
Hilt에 대해 더 자세히 공부하고 싶다면 아래의 Example을 따라서 해보는 것을 추천합니다.
https://codelabs.developers.google.com/codelabs/android-hilt#0
Using Hilt in your Android app | Google Codelabs
In this codelab, you’ll build an Android app that uses Hilt to do Dependency Injection.
codelabs.developers.google.com
여기서 설명하는 방식으로는 Hilt가 이 프로젝트에 미치는 영향을 파악하기에 어려움이 있으므로 나중에 한번 더 언급할 예정입니다.
여기까지 메인 Activity와 layout에 대해 확인하였습니다.
다음으로는 메인 Activity에서 nav_graph에 지정되어 있는 Fragment를 따라서 확인해보겠습니다.
'Android > 꼼꼼한 리뷰' 카테고리의 다른 글
[Sunflower] Navigation 리뷰(1/3) (with ViewPager2 + TabLayout) (0) | 2021.01.04 |
---|---|
[Sunflower] Sunflower 프로젝트 살펴보기(using Jetpack) (0) | 2020.12.30 |
댓글