Since you are using Android Jetpack, I can assume that you also use Navigation Component.
If you want a ViewModel to only stay active when you are in certain fragments, you can create a navigation chart for those fragments, so that the shared ViewModel only lives while you are browsing between those fragments and is destroyed when you leave them.
Imagine that your app has these fragments,
- VehicleFragment: inside this fragment you have tabs(SedanFragment, PickupFragment,
OffroadFragment, etc.)
- UserProfileFragment
- LoginFragment
- etc.
And you want to keep a ViewModel alive while you are browsing between Fragment Vehicles and its different tabs.
Well, create a nested navigation chart for them like this.
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main_navigation.xml"
app:startDestination="@id/MainFragment">
<fragment
android:id="@+id/MainFragment"
android:name="com.fortatic.apps.guesstheword.ui.welcome.MainFragment"
android:label="MainFragment"
tools:layout="@layout/fragment_main">
<action
android:id="@+id/action_mainFragment_to_vehicleGraph"
app:destination="@id/vehicleGraph" />
</fragment>
<navigation
android:id="@+id/vehicleGraph"
app:startDestination="@id/vehicleFragment" >
<fragment
android:id="@+id/vehicleFragment"
android:name="com.fortatic.apps.guesstheword.ui.game.VehicleFragment"
android:label="VehicleFragment"
tools:layout="@layout/fragment_vehicle">
<action
android:id="@+id/action_fragmentVehicle_to_sedanFragment"
app:destination="@id/sedanFragment"/>
<action
android:id="@+id/action_fragmentVehicle_to_pickupsFragment"
app:destination="@id/pickupsFragment"/>
<action
android:id="@+id/action_fragmentVehicle_to_offroadFragment"
app:destination="@id/offroadFragment"/>
</fragment>
<fragment
android:id="@+id/sedanFragment"
android:name="com.fortatic.apps.guesstheword.ui.score.SedanFragment"
android:label="SedanFragment"
tools:layout="@layout/fragment_sedan">
...
</fragment>
<fragment
android:id="@+id/pickupsFragment"
android:name="com.fortatic.apps.guesstheword.ui.score.PickupFragment"
android:label="PickupFragment"
tools:layout="@layout/fragment_pickups">
...
</fragment>
<fragment
android:id="@+id/offroadFragment"
android:name="com.fortatic.apps.guesstheword.ui.score.OffroadFragment"
android:label="OffroadFragment"
tools:layout="@layout/fragment_offroad">
...
</fragment>
</navigation>
</navigation>
Once you have created the nested navigation graph, simply request an instance of ViewModel using:
private val mySharedViewModel: SharedViewModel by navGraphViewModels(R.id.myNestedGraph) {
//defaultViewModelProviderFactory or the ViewModelProvider.Factory you are using.
}
You can find more details in this answer
ViewModel
to the lifecycle of the parent Fragment instead of the Activity? – NephronViewModelProviders.of(parentFragment!!, viewModelFactory)
– BenchViewModelProviders.of(parentFragment!!, viewModelFactory)
coz you never know who theparentFragment
is! If the the fragment is a child fragment of a child fragment then scoping yourViewModel
with theparentFragment
will create a newViewModel
instead. – Terra