Navigation Component中navGraphViewModels与activityViewModels的区别
你之所以觉得两者差异不大,是因为测试场景还没触碰到它们的生命周期边界,下面直接说核心区别:
1. 生命周期绑定的对象完全不同
by activityViewModels():ViewModel的生命周期和整个Activity绑定,只要Activity没被系统销毁,这个ViewModel就会一直存在。by navGraphViewModels(R.id.navigation):ViewModel的生命周期和**你指定的那个导航图(NavGraph)**绑定,只有当这个导航图从返回栈中被彻底移除时(比如从dailyWorkoutLogFragment返回calendarFragment,此时嵌套的navigation子导航图会被弹出),ViewModel才会被销毁回收。
2. 数据共享的作用域不一样
activityViewModels是全局共享:Activity下所有Fragment,不管属于哪个导航分支(比如你的calendarFragment和dailyWorkoutLogFragment所在的完全不同的导航路径),都能拿到同一个ViewModel实例,数据全Activity通用。navGraphViewModels是局部共享:只有指定导航图内部的Fragment才能共享这个ViewModel,比如你嵌套的navigation子图里的addRoutine、workoutListTabFragment、writeDetailFragment这几个页面可以共享,而calendarFragment或者dailyWorkoutLogFragment根本拿不到这个ViewModel的实例。
3. 内存资源的回收时机不同
- 用
activityViewModels的ViewModel,只要Activity活着就不会被回收,哪怕你已经退出了某个导航流程,数据还是会一直占着内存,适合存放全局通用的数据(比如用户登录状态、全局配置)。 - 用
navGraphViewModels的ViewModel,当你退出对应的导航图时(比如完成健身日志填写后回到日历页),ViewModel会自动被销毁,内存会被释放,适合存放某个流程内的临时数据(比如你这个填写日志的临时内容,退出流程后就不需要保留了)。
结合你的导航图场景补充
你现在测试时返回页面数据都保留,是因为你一直在嵌套的navigation子图内部跳转,这个子导航图还在返回栈里,所以navGraphViewModels的ViewModel还活着;但如果你从dailyWorkoutLogFragment返回calendarFragment,此时navigation子导航图被弹出,navGraphViewModels的ViewModel就会被销毁,下次再进入这个子导航图会创建新的实例,而activityViewModels的ViewModel还是原来的,数据依然保留。
你的导航图代码:
<?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_graph" app:startDestination="@id/calendarFragment"> <fragment android:id="@+id/calendarFragment" android:name="com.example.lightweight.presentation.ui.calendar.CalendarFragment" android:label="fragment_calendar" tools:layout="@layout/fragment_calendar" /> <fragment android:id="@+id/dailyWorkoutLogFragment" android:name="com.example.lightweight.presentation.ui.write.DailyWorkoutLogFragment" android:label="fragment_daily_workout_log" tools:layout="@layout/fragment_daily_workout_log" > <action android:id="@+id/action_dailyWorkoutLogFragment_to_navigation" app:destination="@id/navigation" /> </fragment> <navigation android:id="@+id/navigation" app:startDestination="@id/addRoutine"> <fragment android:id="@+id/workoutListTabFragment" android:name="com.example.lightweight.presentation.ui.write.WorkoutListTabFragment" android:label="WorkoutListTabFragment" tools:layout="@layout/fragment_workout_list_tab"> <action android:id="@+id/action_workoutListTabFragment_to_writeDetailFragment" app:destination="@id/writeDetailFragment" /> </fragment> <fragment android:id="@+id/writeDetailFragment" android:name="com.example.lightweight.presentation.ui.write.WriteDetailFragment" android:label="fragment_write_detail" tools:layout="@layout/fragment_write_detail"> <argument android:name="workout" android:defaultValue="@null" app:argType="string" app:nullable="true" /> <action android:id="@+id/action_writeDetailFragment_to_addRoutine" app:destination="@id/addRoutine" /> </fragment> <fragment android:id="@+id/addRoutine" android:name="com.example.lightweight.presentation.ui.write.AddRoutineFragment" android:label="fragment_add_routine" tools:layout="@layout/fragment_add_routine"> <action android:id="@+id/action_addRoutine_to_workoutListTabFragment" app:destination="@id/workoutListTabFragment" /> </fragment> </navigation> </navigation>
内容的提问来源于stack exchange,提问作者ybybyb
相关产品推荐
相关产品推荐

