Android 从Dagger模块方法调用inject()-错误的做法?

Android 从Dagger模块方法调用inject()-错误的做法?,android,mvp,dagger,Android,Mvp,Dagger,我还不熟悉依赖注入,我尝试使用MVP设计模式来实现我的应用程序。我为每个视图使用一个范围图。在通读之后,我决定将我的适配器视为视图的一部分 在我的示例中,视图是一个片段。我创建了一个模块[称为FragmentModule],它提供了演示者和视图 在我开始胡闹之前,模块只注入了片段,并通过调用其构造函数提供了片段适配器 模块: @Module( overrides = true, includes = BaseFragmentModule.class,

我还不熟悉依赖注入,我尝试使用MVP设计模式来实现我的应用程序。我为每个视图使用一个范围图。在通读之后,我决定将我的适配器视为视图的一部分

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

在我开始胡闹之前,模块只注入了片段,并通过调用其构造函数提供了片段适配器

模块:

@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;
    // ... // 
}
private Context mContext;
private CustomListener mListener;

public FragmentAdapter(MyFragment iFragment)
{
    mContext = iFragment.getActivity();
    mListener = iFragment;
    // ... // 
}
这可能仍然是“正确的做法”,但我想讨论一下我目前的做法,所以请继续阅读

然后我再次重写它,以便FragmentAdapter引用Fragment实例。然后,我在碎片适配器构造函数中分配了上下文和侦听器

private MyFragment mFragment;

@Provides
@Singleton
public FragmentAdapter provideAdapter() {
    return new FragmentAdapter(mFragment);
}
适配器构造函数如下所示:

private Context mContext;
private CustomListener mListener;

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

public FragmentAdapter(MyFragment iFragment)
{
    mContext = iFragment.getActivity();
    mListener = iFragment;
    // ... // 
}
之后,出于某种原因,我决定将上下文注入适配器。所以我继续说: 我让片段模块也注入适配器,如下所示:

@Module(
        overrides = true,
        includes = BaseFragmentModule.class,
        injects = {
                FragmentAdapter.class,
                MyFragment.class,
        }
)
现在我必须学习如何将FragmentAdapter以一种漂亮、干净的方式注入片段的作用域ObjectGraph。首先,我从FragmentAdapter构造函数调用了inject()

private final Context mContext;
private final MyListener mListener;

@Inject
public FragmentAdapter(Context context, MyListener listener)
{
    mContext = context;
    mListener = listener;
    // ... // 
}
碎片模块:

// ... //
private MyFragment mFragment;
// ... //
@Provides
@Singleton
public FragmentAdapter provideAdapter() {
    return new FragmentAdapter(mFragment);
}
// ... //
碎片适配器

@Inject Context mContext;
@Inject MyListener mListener;

public FragmentAdapter(MyFragment iFragment)
{
    iFragment.getObjectGraph().inject(this);
    // ... // 
}
同样,出于某种原因(请记住我正在学习…)-我想让注入工作,而不必将片段实例传递给片段适配器构造函数,因此我最终从模块类中调用注入()

    @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注入实现适配器和片段依赖关系?为什么


非常感谢您的反馈

在我看来,应该尽量避免使用
ObjectGraph.inject(…)
。相反,您希望进行构造函数注入:在构造函数中传递注入的依赖项

private MyFragment mFragment;

@Provides
@Singleton
public FragmentAdapter provideAdapter() {
    return new FragmentAdapter(mFragment);
}
您可以通过向构造函数添加
@Inject
注释来完成此操作:

private final Context mContext;
private final MyListener mListener;

@Inject
public FragmentAdapter(Context context, MyListener listener)
{
    mContext = context;
    mListener = listener;
    // ... // 
}
现在,您不再需要
provideApter()
,因为Dagger可以识别构造函数上的
@Inject
注释。您确实需要提供
Context
MyListener
实例,我相信您已经在这样做了

话虽如此,我认为不应该注入
MyListener
。它不是您的
片段适配器的依赖项,而是一项功能。只需从
Fragment
类调用
setListener(MyListener)


最后一句话,有时
inject(…)
是不可避免的。特别是当您使用的类的构造函数不是您管理的(例如
活动
片段
)时。

感谢您的输入Niek!我已经同意了。我同意你的话——事实上,我最终删除了以前使用的接口,我直接处理适配器中的事件——因为我认为这是视图的一部分。对还是错。。这是一个可扩展的列表视图。