java - Dagger 2 : Injected object might still be null before onAttach is called in fragment

标签 java android mvvm dependency-injection dagger-2

我正在使用 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/

相关文章:

java - 贝塞尔低通算法

android - 在 Android 应用程序 Activity 之间使用单例?

c# - 将 ViewModel 投影回模型的最佳方式

java - Android:在通话期间显示消息

java - XSL - 匹配节点的文本并附加另一个节点作为同级节点

java - JMS QueueSender 线程安全吗?

android - 在用Kotlin编写的自定义插件中访问gradle Android插件

android - 某些国家/地区在 Google Play 开发者控制台中被禁用

android - MVVM 的 RoboBinding 与 Android 绑定(bind)

wpf - 有人在Revit环境中使用WPF/MVVM吗?