从Dagger模块方法调用inject() - 不好的做法?

时间:2014-12-12 10:38:41

标签: android mvp dagger

我还是新的依赖注入,我尝试使用 MVP 设计模式实现我的应用程序。我为每个视图使用范围图。我决定在阅读this great article后,我的适配器应被视为View的一部分。

我的示例中的视图是片段。我创建了一个模块[称为 FragmentModule ],它提供了 Presenter View

在我开始搞乱之前,模块只注入了 Fragment ,并通过调用带有所需参数的构造函数来提供 FragmentAdapter

模块:

@Module(
        overrides = true,
        includes = BaseFragmentModule.class,
        injects = {
                MyFragment.class,
        }
)
public class FragmentModule {

    private MyFragment mFragment;

    // ... // Other methods removed for clarity

    @Provides
    @Singleton
    public FragmentAdapter provideAdapter() {
        return new FragmentAdapter(mFragment.getActivity(), mFragment);
    }

    // ... //
}

FragmentAdapter 构造函数看起来像这样:

private Context mContext;
private CustomListener mListener;

public FragmentAdapter(Context context, CustomListener listener)
{
    mContext = context;
    mListener = listener;
    // ... // 
}

这可能仍然是#34;正确的做法"但我想讨论我目前的做法,所以继续阅读!

然后我再次重新编写它,以便 FragmentAdapter 引用 Fragment 实例。然后我在 FragmentAdapter 构造函数中指定了Context和Listener。

private MyFragment mFragment;

@Provides
@Singleton
public FragmentAdapter provideAdapter() {
    return new FragmentAdapter(mFragment);
}

Adapter构造函数如下所示:

private Context mContext;
private CustomListener mListener;

public FragmentAdapter(MyFragment iFragment)
{
    mContext = iFragment.getActivity();
    mListener = iFragment;
    // ... // 
}

之后我决定出于某种原因我想将Context注入适配器。所以我继续说: 我也将 FragmentModule 注入了适配器,如下所示:

@Module(
        overrides = true,
        includes = BaseFragmentModule.class,
        injects = {
                FragmentAdapter.class,
                MyFragment.class,
        }
)

现在我必须学习如何以一种漂亮,干净的方式将 FragmentAdapter 注入到Fragment的作用域ObjectGraph中。首先,我从 FragmentAdapter 构造函数中调用 inject()

FragmentModule:

// ... //
private MyFragment mFragment;
// ... //
@Provides
@Singleton
public FragmentAdapter provideAdapter() {
    return new FragmentAdapter(mFragment);
}
// ... //

FragmentAdapter

@Inject Context mContext;
@Inject MyListener mListener;

public FragmentAdapter(MyFragment iFragment)
{
    iFragment.getObjectGraph().inject(this);
    // ... // 
}

再次,出于某种原因(记得我正在学习..) - 我想让注入工作而不必将 Fragment 实例传递给 FragmentAdapter 构造函数,所以我最终在Module类中调用 inject()

    @Provides
    @Singleton
    public FragmentAdapter provideAdapter() {
        if (mAdapter == null) {
            mAdapter = new FragmentAdapter();
            mFragment.getObjectGraph().inject(mAdapter);
            mAdapter.initialize(); // Code moved from constructor which depends on injected members
        }
        return mAdapter;
    }

现在我很好奇 - 你觉得这里最好的做法是什么?如何使用Dagger注入实现Adapter和Fragment依赖?为什么?

非常感谢您的反馈!

1 个答案:

答案 0 :(得分:1)

我看到它的方式,ObjectGraph.inject(...)应该尽可能避免。相反,您希望执行构造函数注入:在构造函数中传递注入的依赖项。

您可以通过向构造函数添加@Inject注释来执行此操作:

private final Context mContext;
private final MyListener mListener;

@Inject
public FragmentAdapter(Context context, MyListener listener)
{
    mContext = context;
    mListener = listener;
    // ... // 
}

现在,您不再需要provideAdapter(),因为Dagger识别构造函数上的@Inject注释。您需要提供我认为您已经在做的ContextMyListener个实例。

如果说过,我不相信MyListener应该被注入。它不是您FragmentAdapter的依赖项,而是一项功能。只需拨打setListener(MyListener)课程中的Fragment即可。

最后一句话,有时inject(...)是无法避免的。特别是当您使用的是您没有管理的构造函数的类时(例如ActivityFragment)。