Dagger 2:在片段中调用onAttach之前,注入的对象可能仍为null
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Dagger 2:在片段中调用onAttach之前,注入的对象可能仍为null相关的知识,希望对你有一定的参考价值。
我正在使用Dagger将viewModel注入片段:
class BaseFragment<T extends BaseViewModel> extends Fragment {
@Inject T viewModel;
@Override
public void onAttach(Context context) {
super.onAttach(context);
if(viewModel == null) {
throw new RuntimeException("Viewmodel was null: "+getClass());
}
viewModel.setContext(context);
viewModel.onAttach(context);
}
}
class MyFragment extends BaseFragment<MyViewModel> {
public MyFragment() {
MyApp.getInstance().getComponent().inject(this);
//viewModel should be available at this point, before OnAttach is called
}
}
所以简而言之,我在构造函数中注入了viewModel,如果onAttach仍然为null,则说明错了。
而这种情况从未发生过,除非它有100万次中的1次。只是几次崩溃。但无法弄清楚为什么。这种方法有误吗? Dagger是否有某种方式存在参数化对象的问题?
我不直接实例化BaseFragment所以类型应该工作,它通常这样做,那么为什么它在某些情况下不起作用?
注入Fragment的构造函数是不正确的:
public MyFragment() {
//MyApp.getInstance().getComponent().inject(this);
//don't inject in a constructor!
}
虽然这可能适用于非常简单的工作流程,但它无法正确处理Fragment生命周期。特别是,存在片段存在但与活动分离的情况。当发生这种情况并且有必要将片段显示给再次用户时,android OS将尝试重新附加缓存的片段而不调用构造函数(因为实例已经存在)。因为你依赖的假设是在onAttach
之前总是新建一个构造函数,所以可以想象这种情况会导致你的崩溃。
虽然通过与您的应用程序的正常交互可能很难自己复制此问题,但我怀疑如果您在启用System/DeveloperOptions/Don't keep activities
的情况下测试应用程序,则更有可能遇到此问题。
注入片段子类的正确方法是在onAttach(Context context)
中:
@Override
public void onAttach(Context context) {
MyApp.getInstance().getComponent().inject(this);
super(context); //call super
}
这将更准确地跟踪Fragment生命周期。
请注意super
通话前的注射请求。这是根据Dagger official documentation的建议。
以上是关于Dagger 2:在片段中调用onAttach之前,注入的对象可能仍为null的主要内容,如果未能解决你的问题,请参考以下文章
替换未调用 onAttach、onCreate、onCreateView 等的活动中的片段
在 onActivityCreated() 之后再次调用 Fragment 的 onAttach()
是否最好使用 Activity.onAttachFragment 或 Fragment.onAttach 在 Activity 和嵌套片段之间进行通信?