You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Hilt实现Jetpack Navigation下两Fragment限定生命周期共享ViewModel

使用Jetpack Navigation + Hilt 实现指定范围共享ViewModel的实现方案

方案一:官方Hilt Navigation扩展实现(推荐,无需自定义Scope)

该方案利用导航图嵌套结构的生命周期自动管理ViewModel作用域,无需手动维护自定义Scope,适配性和稳定性更高。

步骤1:添加依赖

确保模块级build.gradle中引入Hilt与Navigation的集成依赖:

dependencies {
    implementation "androidx.hilt:hilt-navigation-fragment:1.2.0"
    // 需提前引入Jetpack Navigation、Hilt核心基础依赖
}

步骤2:配置嵌套导航图

将Fragment B、Fragment C归入同一个嵌套导航图,该子图的生命周期将与ViewModel B完全对齐:

<!-- 主导航图nav_graph_main.xml -->
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/nav_graph_main"
    app:startDestination="@id/fragmentA">

    <fragment
        android:id="@+id/fragmentA"
        android:name="com.yourpackage.FragmentA" />

    <!-- 嵌套子图:覆盖B到C的完整流程,生命周期从进入B开始,到退回A时销毁 -->
    <navigation
        android:id="@+id/nav_graph_b_flow"
        app:startDestination="@id/fragmentB">
        <fragment
            android:id="@+id/fragmentB"
            android:name="com.yourpackage.FragmentB" />
        <fragment
            android:id="@+id/fragmentC"
            android:name="com.yourpackage.FragmentC" />
    </navigation>
</navigation>

步骤3:定义ViewModel B

正常使用Hilt的ViewModel注解即可,无需额外配置作用域:

@HiltViewModel
class ViewModelB @Inject constructor() : ViewModel() {
    // 此处编写业务逻辑
}

步骤4:Fragment中获取共享ViewModel

在Fragment B和Fragment C中,通过navGraphViewModels指定嵌套子图的ID,即可获取同一实例:

// Fragment B代码
@AndroidEntryPoint
class FragmentB : Fragment() {
    private val viewModelB: ViewModelB by navGraphViewModels(R.id.nav_graph_b_flow) {
        defaultViewModelProviderFactory
    }
}

// Fragment C代码,实现完全一致
@AndroidEntryPoint
class FragmentC : Fragment() {
    private val viewModelB: ViewModelB by navGraphViewModels(R.id.nav_graph_b_flow) {
        defaultViewModelProviderFactory
    }
}

该实现下,ViewModel B会在用户第一次进入Fragment B时创建,在用户从Fragment B回退到Fragment A、嵌套子图完全出栈时自动销毁,完全匹配需求。

方案二:自定义Hilt Scope实现

如果需要更灵活的作用域控制,可通过自定义Hilt Scope实现,该方案需要手动管理作用域生命周期。

步骤1:定义自定义作用域注解

@Scope
@MustBeDocumented
@Retention(AnnotationRetention.RUNTIME)
annotation class BFlowScope

步骤2:定义作用域对应的Hilt Component

@BFlowScope
@DefineComponent(parent = ActivityComponent::class)
interface BFlowComponent {
    @DefineComponent.Builder
    interface Builder {
        fun build(): BFlowComponent
    }
}

步骤3:定义EntryPoint提供Component构造入口

@EntryPoint
@InstallIn(SingletonComponent::class)
interface BFlowComponentEntryPoint {
    fun bFlowComponentBuilder(): BFlowComponent.Builder
}

步骤4:给ViewModel B标注自定义作用域

@BFlowScope
class ViewModelB @Inject constructor() : ViewModel() {
    // 业务逻辑
}

步骤5:管理Component生命周期

在Fragment B的onCreate方法中初始化Component,监听导航回退事件,当嵌套子图完全出栈时手动销毁Component实例,避免内存泄漏。


内容的提问来源于stack exchange,提问作者PhongBM

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 11:18:01