Dagger Hilt在自定义View中注入对象为null的问题排查
Dagger Hilt注入自定义View时构造方法中对象为null的原因及解决办法
问题背景
你在XML布局中声明的CustomView(继承自LinearLayout的BaseWidget)添加了@AndroidEntryPoint注解,尝试注入ExampleClass,但发现构造方法中注入的exampleClassInjected始终为null,但等到Fragment的onViewCreated()执行后,该对象又能正常使用。Fragment和Activity都已正确添加@AndroidEntryPoint注解。
核心原因
Hilt对View的注入时机和Fragment/Activity存在差异:
- 当LayoutInflater从XML加载View时,只会调用View的构造方法完成基础初始化,此时Hilt的注入逻辑还未触发。
- Hilt是通过宿主Fragment/Activity的注入流程来完成View的依赖注入的,这个过程要等到View被添加到宿主的视图层级之后,也就是Fragment执行到
onViewCreated()阶段前后才会完成。所以在View的构造方法中,注入对象还未被初始化,自然为null。
解决方案
1. 延后依赖使用时机到View生命周期方法
把需要使用注入对象的逻辑,放到View的onFinishInflate()或onAttachedToWindow()方法中,这两个方法的调用时机都在Hilt完成注入之后:
@AndroidEntryPoint public class CustomView extends BaseWidget { @Inject ExampleClass exampleClassInjected; public CustomView(Context context, AttributeSet attrs) { super(context, attrs); // 此处不要调用exampleClassInjected,注入未完成 } @Override protected void onFinishInflate() { super.onFinishInflate(); // 这里可以安全使用注入的对象 exampleClassInjected.someMethod(); } }
2. 在Fragment中手动触发View初始化
如果需要在View初始化阶段完成某些操作,可以给View添加一个初始化方法,在Fragment的onViewCreated()中调用:
// CustomView中 @AndroidEntryPoint public class CustomView extends BaseWidget { @Inject ExampleClass exampleClassInjected; public CustomView(Context context, AttributeSet attrs) { super(context, attrs); } // 自定义初始化方法 public void setup() { exampleClassInjected.doWork(); } } // ExampleFragment中 @AndroidEntryPoint public class ExampleFragment extends Fragment { @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); CustomView customView = view.findViewById(R.id.customview); // 此时注入已完成,可安全调用setup方法 customView.setup(); } }
注意事项
- 不要给
BaseWidget添加@AndroidEntryPoint注解,Hilt只需要直接在需要注入的View类上添加该注解即可,父类无需重复标注。 - 确保宿主Fragment和Activity的
@AndroidEntryPoint注解没有遗漏,否则View的注入流程会无法触发。
内容的提问来源于stack exchange,提问作者Borja
相关产品推荐
相关产品推荐

