Android中使用Dagger向非页面类注入单例为空如何解决
问题根因
你手动通过new BackendImp()创建实例时,Dagger不会自动识别类内部的@Inject注解并完成依赖注入,必须主动触发注入流程或者通过构造函数注入依赖。另外你将BackendImp的注入方法定义在了@PerActivity作用域的AbstractActivityComponent中,但BackendImp是全局单例,和Activity生命周期无关联,配置本身也不匹配。
最优解决方案(构造函数注入,符合Dagger最佳实践)
步骤1:修改BackendImp实现构造注入
给BackendImp的构造函数添加@Inject注解,直接通过构造参数传入依赖,无需字段注入:
public class BackendImp implements BackendService { private final DataAccessInterface dataAccessInterface; @Inject public BackendImp(DataAccessInterface dataAccessInterface) { this.dataAccessInterface = dataAccessInterface; } public void save () { Car car = unloadCar(); dataAccessInterface.saveCar(car); } }
步骤2:在ApplicationModule中提供BackendImp单例
新增方法暴露BackendService单例:
@Module public class ApplicationModule { // 原有代码不变 @Provides @Singleton BackendService provideBackendService(BackendImp backendImp) { return backendImp; } }
步骤3:在ApplicationComponent中添加BackendService暴露方法
@Singleton @Component(modules = ApplicationModule.class) public interface ApplicationComponent { // 原有方法保留 Application application(); Context context(); DataAccessInterface dataAccessInterface(); // 新增方法 BackendService backendService(); }
步骤4:修改Application初始化逻辑,从Dagger组件获取实例
不要手动new实例,直接从ApplicationComponent中获取Dagger已经完成依赖注入的实例:
public class MainApp extends Application { public static BackendService backendService; private ApplicationComponent appComponent; @Override public void onCreate () { super.onCreate(); // 初始化ApplicationComponent appComponent = ApplicationComponent.Initializer.init(this); // 从Dagger组件获取已注入完成的实例 backendService = appComponent.backendService(); } // 原有其他代码不变 }
备选方案(手动触发字段注入,无需修改原有BackendImp结构)
如果你不想调整BackendImp的现有结构,也可以主动调用Dagger的注入方法完成字段注入:
步骤1:将BackendImp的注入方法迁移到ApplicationComponent
@Singleton @Component(modules = ApplicationModule.class) public interface ApplicationComponent { // 原有方法保留 void inject(Application application); // 新增BackendImp注入方法 void inject(BackendImp backendImp); }
步骤2:手动new实例后触发注入
public class MainApp extends Application { public static BackendService backendService; private ApplicationComponent appComponent; @Override public void onCreate () { super.onCreate(); appComponent = ApplicationComponent.Initializer.init(this); // 手动创建实例 backendService = new BackendImp(); // 主动触发注入,完成dataAccessInterface的赋值 appComponent.inject((BackendImp) backendService); } // 原有其他代码不变 }
额外优化建议
你之前在AbstractActivityComponent中定义的void inject (BackendImp inject);可以删除了,BackendImp是全局单例,不需要和Activity作用域的组件绑定。
内容的提问来源于stack exchange,提问作者Federremu
相关产品推荐
相关产品推荐

