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

Android Service类能否用构造注入?首次启动崩溃二次启动正常的原因

问题根本原因及解决方案

核心原因分析

1. Android系统实例化Service的强制要求

FirebaseMessagingService属于Android系统托管的组件,系统会在特定场景(比如应用首次启动、首次接收FCM推送)通过反射机制创建其实例,而反射创建的前提是类必须提供无参构造函数。你的MyFirebaseMessagingService仅定义了带@Inject注解的有参构造,完全没有无参构造,这就违反了系统的实例化规则,首次启动时系统直接反射失败抛出InstantiationException。

2. 二次启动正常的原因

首次崩溃会导致应用进程重启,此时你的依赖注入框架(比如Dagger)已经完成了全局组件的初始化,并且通过框架的Android扩展能力(比如Dagger Android的AndroidInjection)接管了Service的实例创建流程。当系统再次尝试获取MyFirebaseMessagingService实例时,会使用DI框架提供的已注入依赖的实例,而非自己通过反射创建,因此不会再触发无参构造的问题。

解决方案

要同时满足系统的实例化要求和依赖注入需求,正确的做法是:

  1. 为MyFirebaseMessagingService添加无参构造函数,供系统反射调用;
  2. 使用字段注入替代构造注入,并在onCreate方法中手动触发依赖注入。

示例代码:

class MyFirebaseMessagingService : FirebaseMessagingService() {
    // 用lateinit修饰字段,等待注入
    @Inject lateinit var repository: Repository

    // 必须保留无参构造,供系统反射实例化
    constructor() : super()

    override fun onCreate() {
        super.onCreate()
        // 触发依赖注入,由DI框架完成repository的初始化
        AndroidInjection.inject(this)
    }

    // 业务逻辑代码...
}

如果坚持使用构造注入,也可以保留带@Inject的有参构造,但必须同时提供无参构造(不过这种硬编码组件创建的方式不推荐,易引发生命周期不一致问题):

class MyFirebaseMessagingService @Inject constructor(private val repository: Repository) :
    FirebaseMessagingService() {
    // 无参构造,委托给有参构造
    constructor() : this(DaggerAppComponent.create().repository)

    // 业务逻辑代码...
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 17:40:40