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