You need to enable JavaScript to run this app. Dagger-Hilt中如何提供Activity实例以注入ViewModel构造函数?
优惠活动
大模型
产品
解决方案
定价
更多

Dagger-Hilt中如何提供Activity实例以注入ViewModel构造函数?

ViewModel构造注入需要Activity实例的解决方案

原则上禁止在ViewModel中持有Activity实例,ViewModel生命周期长于Activity,持有强引用会直接导致内存泄漏,属于违反Android架构设计规范的行为。如果确实有相关需求,可按以下场景选择对应方案:

方案1:使用辅助注入传入Activity(仅用于临时操作,不存储)

如果仅需要在ViewModel初始化时一次性调用Activity的相关方法,不需要长期持有,可以使用Dagger/Hilt的辅助注入能力,无需在Module中预先提供Activity实例:

  • 给ViewModel构造函数添加@AssistedInject注解,替换原有@Inject
  • 给构造函数中的Activity参数添加@Assisted注解
  • 定义辅助注入工厂:
@AssistedFactory
interface MyViewModelFactory {
    fun create(@Assisted activity: AppCompatActivity): MyViewModel
}
  • 在Activity中注入工厂,创建ViewModel时传入当前Activity实例:
@AndroidEntryPoint
class MyActivity : AppCompatActivity() {
    @Inject lateinit var viewModelFactory: MyViewModelFactory
    private val viewModel: MyViewModel by viewModels {
        object : ViewModelProvider.Factory {
            @Suppress("UNCHECKED_CAST")
            override fun <T : ViewModel> create(modelClass: Class<T>): T {
                return viewModelFactory.create(this@MyActivity) as T
            }
        }
    }
}

方案2:事件回调解耦(最推荐)

从架构层面彻底解耦ViewModel和Activity,完全避免持有引用风险:

  • ViewModel内部定义事件类型,通过SharedFlow/LiveData发射事件
  • Activity侧观察事件,收到事件后执行需要Activity实例的操作(弹框、跳转、权限申请等)
    代码示例:
// ViewModel层
class MyViewModel @Inject constructor(
    // 其他注入参数
) : ViewModel() {
    private val _event = MutableSharedFlow<MyEvent>()
    val event = _event.asSharedFlow()

    suspend fun triggerShowDialog() {
        _event.emit(MyEvent.ShowConfirmDialog)
    }
}

sealed class MyEvent {
    object ShowConfirmDialog : MyEvent()
}

// Activity层
lifecycleScope.launch {
    repeatOnLifecycle(Lifecycle.State.STARTED) {
        viewModel.event.collect { event ->
            when(event) {
                is MyEvent.ShowConfirmDialog -> {
                    // 用当前Activity实例弹Dialog
                    AlertDialog.Builder(this@MyActivity)
                        .setMessage("提示")
                        .show()
                }
            }
        }
    }
}

方案3:仅需要Context时注入Activity Context

如果你的需求只是需要Context而不是Activity实例本身,可直接注入Hilt提供的标记@ActivityContext的Context,无需自行在Module中提供:

class MyViewModel @Inject constructor(
    @ActivityContext private val context: Context,
    // 其他注入参数
) : ViewModel() {
    // 直接使用context即可,Hilt会自动绑定当前Activity的上下文
}

特殊场景必须持有Activity引用时,一定要使用弱引用WeakReference<Activity>包裹,且在Activity销毁时及时清空,避免内存泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.10 08:51:02