我正在使用 Dagger 将 viewModel 注入(inject)到 fragment 中:
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
}
}
所以简而言之,我在构造函数中注入(inject) viewModel,如果 onAttach 仍然为 null,则说明有问题。
这种情况永远不会发生,除非十万次中只有一次会发生。只有几次崩溃。但无法弄清楚为什么。这种做法有错吗? Dagger 是否对参数化对象有问题?
我不直接实例化 BaseFragment,因此该类型应该可以工作,而且通常都是这样,那么为什么在某些情况下它不起作用呢?
最佳答案
在 Fragment 的构造函数中注入(inject)是不正确的:
public MyFragment() {
//MyApp.getInstance().getComponent().inject(this);
//don't inject in a constructor!
}
虽然这可能适用于非常简单的工作流程,但它无法正确处理 fragment 生命周期。特别是,存在 Fragment 存在但与 Activity 分离的情况。当发生这种情况并且需要再次向用户显示 Fragment 时,Android 操作系统将尝试重新附加缓存的 Fragment,而不调用构造函数(因为实例已经存在)。因为您依赖于这样的假设:构造函数总是在 before onAttach
之前被新调用。可以想象,这种情况导致了您的崩溃。
虽然通过与应用程序的正常交互可能很难自己复制此问题,但我怀疑如果您使用System/DeveloperOptions/Don't keep activities
测试您的应用程序,您更有可能遇到它。已开启。
注入(inject)Fragment子类的正确方法在 onAttach(Context context)
:
@Override
public void onAttach(Context context) {
MyApp.getInstance().getComponent().inject(this);
super.onAttach(context); //call super.onAttach
}
这将更正确地跟踪 Fragment 生命周期。
注意super
之前的注入(inject)请求称呼。这是根据 Dagger official documentation 中的建议.
关于java - Dagger 2 : Injected object might still be null before onAttach is called in fragment,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46001557/