Android 使用Dagger 2注入子类的最佳方法是什么?

Android 使用Dagger 2注入子类的最佳方法是什么?,android,dependency-injection,dagger,dagger-2,Android,Dependency Injection,Dagger,Dagger 2,我最近开始使用Dagger 2来管理我的应用程序的依赖注入。为了使一些类可测试,我开始创建许多需要注入的类。我能够做到这一点,然而,注入这些新类的过程在我看来有点复杂。让我们举一个例子: 例如,我想从我的RecycleServiceAdapter中测试方法onCreateViewHolder()。为此,我创建了一个工厂,它根据给定的LayoutType返回ViewHolder: public class ViewHolderFactor { public RecyclerView.Vi

我最近开始使用Dagger 2来管理我的应用程序的依赖注入。为了使一些类可测试,我开始创建许多需要注入的类。我能够做到这一点,然而,注入这些新类的过程在我看来有点复杂。让我们举一个例子:

例如,我想从我的RecycleServiceAdapter中测试方法
onCreateViewHolder()
。为此,我创建了一个工厂,它根据给定的LayoutType返回ViewHolder:

public class ViewHolderFactor {

    public RecyclerView.ViewHolder getViewHolder(ViewGroup parent, int viewType) {
        LayoutInflater inflater = this.getLayoutInflater(parent.getContext());
        View view;
        switch (LayoutType.fromInteger(viewType)) {
            case SMALL_VERTICAL:
                view = inflater.inflate(R.layout.rsc_util_item_small, parent, false);
                return new ViewHolder.ItemViewHolder(view);
            case LARGE_VERTICAL:
                view = inflater.inflate(R.layout.rsc_util_item_large, parent, false);
                return new ViewHolder.ItemViewHolder(view);
        }
        return null;
    }

    private LayoutInflater getLayoutInflater(Context context) {
        return LayoutInflater.from(context);
    }

}
通过将上述代码移动到一个单独的类,我可以使用以下方法执行单元测试:

@RunWith(JUnit4.class)
public class TestViewHolderFactor extends TestCase {

    ViewHolderFactor viewHolderFactor;

    @Test
    public void testGetViewHolder () {
        this.viewHolderFactor = Mockito.mock(ViewHolderFactor.class);
        ViewGroup viewGroup = Mockito.mock(ViewGroup.class);
        Mockito.when(viewHolderFactor.getViewHolder(viewGroup, LayoutType.SMALL_VERTICAL.toInteger())).thenCallRealMethod();
        Context context = Mockito.mock(Context.class);
        Mockito.when(viewGroup.getContext()).thenReturn(context);
        LayoutInflater layoutInflater = Mockito.mock(LayoutInflater.class);
        Mockito.when(viewHolderFactor.getLayoutInflater(context)).thenReturn(layoutInflater);
        Mockito.when(layoutInflater.inflate(R.layout.rsc_util_item_small, viewGroup, false)).thenReturn(Mockito.mock(View.class));
        RecyclerView.ViewHolder result = viewHolderFactor.getViewHolder(viewGroup, LayoutType.SMALL_VERTICAL.toInteger());
        assertNotNull(result);
    }

}
问题是:现在,为了让应用程序工作,我还必须将保存实例的outter类注入factor(这是我在创建ViewHolderFactor之前没有做的事情)。最后,我将有一个匕首配置如下:

@Module
public class ModuleBusiness {
    @Provides
    public CharacterUIService provideCharacterService(Picasso picasso, NotificationUtil notificationUtil, ViewHolderFactor viewHolderFactor) {
        return new CharacterUIService(picasso, notificationUtil, viewHolderFactor);
    }
}
其中CharacterUIService是创建包含ViewHolderFactory的RecycleServiceAdapter的新实例的类

public class 
    private ViewHolderFactor 
    @Inject
    public CharacterUIService(ViewHolderFactor viewHolderFactor) {
        this.mViewHolderFactor = viewHolderFactor;
    }

    // ...
}
我需要来自ViewHolderFactor的成员才能注入它

我担心的是需要创建新的全局变量和增加构造函数中传递的参数数量。是否有更好的方法来注入这些子类,或者我认为它是一个好的实践,以便允许单元测试?

我能认为这是一个好的实践,以便允许单元测试?

首先,在我个人看来,我认为你做得太过火了。在您提供的测试用例中,您基本上是在测试android框架本身。如果要测试工厂,应该测试返回的是小项目还是大项目,而不是视图不为null

但是,是的,您的方法似乎是允许单元测试的合理方法

其中CharacterUIService是创建RecycleServiceAdapter的新实例的类

您可能想过度考虑
CharacterUIService
的角色。“创建一个新实例”听起来像是应该由dagger来处理的东西,因为您已经在使用它了

还必须将保存实例的outter类注入工厂

为什么?
ViewHolderFactor
(原文如此!)本身没有依赖项。即使它做到了,是什么阻止了你用匕首创造和注射它呢

class ViewHolderFactor {
    @Inject
    ViewHolderFactor() { // allow for constructor injection
    }
}

class YourAdapter {
    ViewHolderFactor mFactor;

    @Inject // allow for constructor injection
    YourAdapter (ViewHolderFactor factor) {/**/}
}
// now dagger knows how to create that adapter
就让dagger创建适配器


通常,如果支持构造函数注入,则可以删除
@providesSomething()
方法。只需删除整个方法。您在构造函数上有一个
@Inject
注释,所以利用它,让dagger为您编写代码

// CharacterUIService can be constructor injected.
@Provides // DAGGER WILL DO THIS FOR YOU
public CharacterUIService provideCharacterService(Picasso picasso, NotificationUtil notificationUtil, ViewHolderFactor viewHolderFactor) {
    // REMOVE ALL OF THIS.
    return new CharacterUIService(picasso, notificationUtil, viewHolderFactor);
}


所以,虽然我认为通过使事情可测试,你们做得很好,但你们应该再次仔细观察dagger,因为你们显然把很多事情混在了一起。好好看看构造器注入,并利用它,它节省了大量的工作。

BTW:Word“因素”离英语“工厂”很远,所以你可以考虑修改你的代码措辞。你说的对,是打字错误。非常感谢,我确实需要好好看看Dagger,你的评论对我很有帮助。