如何在库的基类Application中注入成员?CoreApplication注入Logger遇空指针
解决库模块CoreApplication的成员注入问题
嘿,我来帮你拆解下这个空指针问题的根源,再给你两个靠谱的解决方案:
问题到底出在哪?
你遇到的空指针完全是Application生命周期执行顺序导致的:
当MainApplication启动时,系统会先调用父类CoreApplication的onCreate()方法,这时候你在MainApplication.onCreate()里才会构建Dagger组件并注入,所以CoreApplication里的@Inject Logger logger还没被赋值,直接调用logger.log()肯定会空指针。
而MainApplication和DetailActivity能正常注入,是因为它们的注入操作都在Dagger组件构建完成之后:
MainApplication是先构建组件注入自身,再用loggerDetailActivity的AndroidInjection.inject(this)是在组件 ready 之后执行的,依赖自然能拿到
解决方案一:延迟CoreApplication的初始化逻辑(推荐,解耦性好)
这个方法不需要修改组件结构,只调整生命周期逻辑:
- 先改
CoreApplication,把依赖使用的逻辑从onCreate()移到一个新方法里:
public class CoreApplication extends Application { @Inject Logger logger; @Override public void onCreate() { super.onCreate(); // 这里先不碰logger,等注入完成再说 } // 新增这个方法,让子类在注入完成后调用 protected void afterInject() { logger.log(); } }
- 然后在
MainApplication的onCreate()里,完成注入后再触发父类的初始化:
public class MainApplication extends CoreApplication implements HasActivityInjector { @Inject Logger logger; @Inject DispatchingAndroidInjector<Activity> dispatchingAndroidInjector; @Override public void onCreate() { super.onCreate(); // 先构建Dagger组件并注入自身 DaggerAppComponent.builder().application(this).build().inject(this); // 现在父类的logger已经被注入了,放心调用 afterInject(); logger.log(); } @Override public DispatchingAndroidInjector<Activity> activityInjector() { return dispatchingAndroidInjector; } }
解决方案二:让CoreApplication直接获取组件注入自身
如果希望CoreApplication自己搞定注入(不需要子类触发),可以调整组件设计,但要注意模块依赖问题:
- 在库模块里定义一个
CoreComponent接口:
// 库模块中的CoreComponent @Singleton public interface CoreComponent { void inject(CoreApplication coreApplication); }
- 让
AppComponent继承这个接口:
@Singleton @Component(modules = { AndroidInjectionModule.class, ApplicationModule.class}) public interface AppComponent extends AndroidInjector<MainApplication>, CoreComponent { @Component.Builder interface Builder { @BindsInstance Builder application(Application application); AppComponent build(); } }
- 修改
CoreApplication的onCreate(),直接构建组件并注入自身:
public class CoreApplication extends Application { @Inject Logger logger; @Override public void onCreate() { super.onCreate(); // 构建组件并注入自己 AppComponent appComponent = DaggerAppComponent.builder().application(this).build(); appComponent.inject(this); logger.log(); } }
⚠️ 注意:这种方式会让库模块依赖应用模块的AppComponent,可能造成循环依赖,所以更推荐第一种方案。
最后验证下
别忘了你已经在ApplicationModule里给Logger加了@Singleton,这样不管是CoreApplication、MainApplication还是DetailActivity,拿到的都是同一个实例,完全符合预期。
内容的提问来源于stack exchange,提问作者lex
相关产品推荐
相关产品推荐

