很少出现空注入字段

Rare occurrence of null injected field

极少数情况下,当我尝试访问注入的字段时,应用程序会崩溃,因为该访问的字段为空。我无法重现它,而且它一开始就不应该发生。 知道为什么会发生这种情况以及如何避免这种情况吗?

该字段正在片段中注入:

public class MyFragment extends Fragment {
    @Inject StubManager mStubManager;
    ....
    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Application.getAppComponent().inject(this);
    }

    @Override
    public void onPrepareOptionsMenu(Menu menu) {
        super.onPrepareOptionsMenu(menu);
        ....
        menu.findItem(R.id.item_id)
            .setEnabled(!mStubManager.isRunning());
    }
}

app 组件如下所示,并在 Application class:

中初始化
@Singleton
@Component(modules = {
        MyModule.class
})
public interface AppComponent {
    StubManager stubManager();

    void inject(MyFragment target);
}

在调用 super 之前将你的 inject 调用移动到 onAttach


David mentioned 一样,如果你有一个 Dagger 大部分时间成功注入的非@Nullable 字段,那么它可能不是 Dagger 错误,而是 Android 生命周期或Java 多线程。我猜前者发生在这里。

虽然我在代码或文档中没有明确的理由,anecdotally there seem to be cases where the options menu is prepared before onCreate, and a cursory glance at the Android open source code for FragmentManager and Activity (as well as the menu docs) 建议 Fragment 不能保证被创建并且选项菜单被认为是打开的,只要操作酒吧是可见的。如果是这样,这就是您将从注入字段中读取 null 值的情况。您可以通过打开选项菜单(如果您没有使用 ActionBar)、使用主页按钮或单击通知离开您的 Activity,然后返回到您的 Activity 来对此进行测试] 这样它就必须重新附加片段并重新创建其选项菜单。如果您启用开发选项 "Don't keep activities" 来模拟会导致您的 Activity 被破坏的内存压力,这可能更容易重现,否则这在用户的设备上会相对随机且不常见。

我怀疑你的注射可能也发生了晚期:请注意onAttach is called before onCreate is called, such that the docs for dagger.android suggest injecting in onAttach before the call to super.onAttach。这是在 Fragment 中执行注入的最早、最一致和推荐的位置,特别是如果您的 Fragment 继承自基础 Fragment class:如果 superclass 有任何 @Inject 字段,它在 onCreateonAttach 中使用,它们也将 null 与您的 inject 呼叫所在的位置。