I would like to implement a navigation logic based in the Android Navigation Component in it's more updated version (2.4.0-beta02) but I'm facing some kind of issues (or non expected behaviors) related with the Android lifeycle.
My main problem is that each time you change a tab, fragments are totally recreated which means that onCreate() method it's called every time the tab is changed. I understand that for performance reasons, fragments call onDestroyView() method each time you left the tab associated with it and then when you came back to that tab onCreateView() method will be called. Actually I don't know if my implementation of the Navigation Component and it's behavior it's correct or not and I would like to know how correctly implement it.
My actual implementation looks like this:
Gradle file:
def navigation = "2.4.0-beta02"
implementation "androidx.navigation:navigation-runtime-ktx:$navigation"
implementation "androidx.navigation:navigation-fragment-ktx:$navigation"
implementation "androidx.navigation:navigation-fragment-ktx:$navigation"
implementation "androidx.navigation:navigation-ui-ktx:$navigation"
The activity that holds my tabs:
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private lateinit var navController: NavController
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_container) as NavHostFragment
navController = navHostFragment.navController
binding.bottomNav.setupWithNavController(navController)
}
}
The activity layout:
<?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:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/nav_host_container"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:name="androidx.navigation.fragment.NavHostFragment"
app:navGraph="@navigation/nav_graph"
app:defaultNavHost="true" />
<com.google.android.material.
bottomnavigation.BottomNavigationView
android:id="@+id/bottom_nav"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="0dp"
android:layout_marginEnd="0dp"
android:background="@android:color/white"
app:itemIconTint="@color/gray"
app:itemRippleColor="@android:color/transparent"
app:itemTextColor="@color/gray"
app:labelVisibilityMode="unlabeled"
app:menu="@menu/bottom_nav_menu" />
</LinearLayout>
Graph:
<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/home">
<include app:graph="@navigation/home"/>
<include app:graph="@navigation/profile"/>
</navigation>
Navigation Home:
<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"
android:id="@+id/home"
app:startDestination="@+id/homeFragmentNavigation">
<fragment
android:id="@+id/homeFragmentNavigation"
android:name="com.tayloring.android.view.page.tabs.HomeFragment"
android:label="@string/title_home"
tools:layout="@layout/fragment_home"/>
</fragment>
</navigation>
Secondary 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"
android:id="@+id/profile"
app:startDestination="@+id/profileFragmentNavigation">
<fragment
android:id="@+id/profileFragmentNavigation"
android:name="com.tayloring.android.view
.page.user.ProfileFragment"
android:label="@string/title_profile"
tools:layout="@layout/fragment_profile"
</fragment>
</navigation>
Secondary fragment:
class ProfileFragment : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
println("I'M ALWAYS CALLED")
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_profile, container, false)
}
}
Also I tried this repository https://github.com/android/architecture-components-samples/tree/master/NavigationAdvancedSample which it's the example that some moderns posts of medium talks about when they are talking about the Navigation Component, but it is outdated and it's Navigation version is older.
The Navigation Component calls onDestroy() method each time a tab it's changed so it's the normal behaviour.