더 이상 Navigation Component에 한계는 없어보입니다.

  • Dagger 이슈는 Lazy 인젝션으로 해결가능합니다.
  • SharedElementTransition은 이제 네비게이션 컴포넌트에서 공식적으로 지원합니다.

 


Navigation Component의 한계

Dagger와 Databinding 그리고 fragment의 초기화 문제

어떤 액티비티가 xml 레이아웃을 dagger를 이용하여 바인딩객체를 주인한다고 가정하자. 이때 액티비티의 xml 레이아웃내에 <fragment> element를 써서 프레그먼트를 초기화 하는 경우 액티비티의 레이아웃조차도 인플레이팅이 끝나지 않아 context가 없는상태에서 fragment를 인플레이팅 하려고하니 context 관련해서 nullpointer exception이 발생한다.
MainActivity.kt

class MainActivity : DaggerAppCompatActivity() {
    ...
    @Inject
    lateinit var binding: MainActivityBinding
    ....
}

 
main_activity.xml

<?xml version="1.0" encoding="utf-8"?>
<layout>
    <data>
    ...
    </data>
    <android.support.constraint.ConstraintLayout
        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"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <fragment
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/my_nav_host_fragment"
            android:name="androidx.navigation.fragment.NavHostFragment"
            app:navGraph="@navigation/nav_graph"
            app:defaultNavHost="true"
            />
    </android.support.constraint.ConstraintLayout>
</layout>

 
해결책은 <fragment> element는 사용할 수가 없으니 container를 사용하고, 프레그먼트 매니저를 통해 트랜잭션을 한다.
 
MainActivity.kt

class MainActivity : DaggerAppCompatActivity() {
    ...
    @Inject
    lateinit var binding: MainActivityBinding
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        if (savedInstanceState == null) {
            val navHostFragment = NavHostFragment.create(R.navigation.nav_graph)
            supportFragmentManager.beginTransaction()
                    .setPrimaryNavigationFragment(navHostFragment)
                    .replace(R.id.container, navHostFragment)
                    .commitNow()
        }
    }
}

 
main_activity.xml

<?xml version="1.0" encoding="utf-8"?>
<layout>
    <data>
    ...
    </data>
    <android.support.constraint.ConstraintLayout
        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"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".ui.card.CardActivity">
        <FrameLayout
            android:id="@+id/container"
            android:layout_width="0dp"
            android:layout_height="0dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"/>
    </android.support.constraint.ConstraintLayout>
</layout>

 

Shared Element Transition 사용 불가능

네비게이션 컴포넌트 이용시 프레그먼트간의 화면 전환시 특정뷰를 자연스럽게 이동시키거나 확대시키는 Shared Element Transition를 이용할 수가 없다. 프레그먼트 트랜지션만 지원한다.
Shared Element Transition을 이용하고자 한다면 Navigation은 잠시 접어두도록하자.
아직 알파버전단계이니 추후 Shared Element Transition도 지원하지 않을까 하고 기대한다.
 
결론 : 위의 두가지 한계가 있다하더라도 첫번째 이슈는 우회적으로 해결할 수 있는 방법이 있으며, UI-Flow를 한눈에 볼수 있고 백스택 관리를 할 필요없다는 점, 딥링크자연스럽게 움직인다는 점, NavigationView 와 NavigationDrawer등 다른 컴포넌트와도 잘 어울리는점 등 여러가지 장점이 있다. SharedElementTransition만 아니라면 개발속도와 유지보수를 위해 사용을 고려해보는것도 나쁘지 않다.

카테고리: 미분류

0개의 댓글

답글 남기기

Avatar placeholder

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다.