使用Hilt标注@Singleton的Android Service出现2个实例问题求助
问题根因
你的问题核心是Android系统管控的四大组件(Service/Activity等)不受Hilt依赖注入容器的实例生命周期管控,你目前的两个实例分别来自两个完全独立的实例化路径:
- 系统收到
startService请求后,反射调用Service构造方法创建的实例 - Hilt在注入
Connection类的DeviceConnectionService字段时,调用带@Inject注解的构造方法新创建的实例
你给Service添加的@Singleton注解完全无效,因为@AndroidEntryPoint注解的作用仅为让Hilt给组件内部的注入字段赋值,不会将组件本身注册到Hilt的依赖容器中做单例管控。
解决方案
推荐两种可行方案,优先选方案二:
方案一:通过Service绑定机制获取系统创建的Service实例
- 改造
DeviceConnectionService添加Binder实现,用于返回当前Service实例:
@AndroidEntryPoint public class DeviceConnectionService extends Service { public class LocalBinder extends Binder { public DeviceConnectionService getService() { return DeviceConnectionService.this; } } private final IBinder binder = new LocalBinder(); @Override public IBinder onBind(Intent intent) { return binder; } // 其余原有代码 }
- 移除
Connection类中直接注入DeviceConnectionService的代码,改用ServiceConnection绑定Service后获取实例,保证拿到的是系统创建的唯一实例。
方案二(更推荐):抽离业务逻辑到独立单例类,解耦业务与Service组件
Service作为Android系统组件,仅负责生命周期管控、前台服务注册等系统级操作,不要承载业务逻辑:
- 新建独立的单例业务类承载所有连接操作逻辑:
@Singleton public class DeviceConnectionManager { // 把原Service中所有业务逻辑、对外操作方法移到这里 public void connect() {} public void disconnect() {} }
- Service和Connection类都注入该单例类做业务交互:
@AndroidEntryPoint public class DeviceConnectionService extends Service { @Inject DeviceConnectionManager connectionManager; // Service仅做生命周期、系统事件相关处理,业务逻辑全部调用connectionManager执行 }
@Singleton public class Connection implements IHololensConnection { @Inject DeviceConnectionManager connectionManager; // 所有操作直接调用connectionManager,不需要持有Service实例 }
该方案完全规避了直接持有Service实例的问题,也符合架构分层的最佳实践。
内容的提问来源于stack exchange,提问作者user16413208
相关产品推荐
相关产品推荐

