簡體   English   中英

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

[英]What is the best way to inject subclasses using Dagger 2?

我最近開始使用 Dagger 2 來管理我的應用程序的依賴注入。 為了使某些類可測試,我開始創建許多需要注入的類。 我能夠這樣做,但是,注入這些新類的過程對我來說看起來有點復雜。 讓我們舉個例子:

例如,我想測試我的 RecyclerViewAdapter 中的onCreateViewHolder()方法。 為此,我創建了一個 Factory,它根據給定的 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);
    }

}

問題是:現在,為了使應用程序正常工作,我還必須將保存實例的外部類注入到因子(在創建 ViewHolderFactor 之前我沒有做的事情)。 最后,我將有一個這樣的 Dagger 配置:

@Module
public class ModuleBusiness {
    @Provides
    public CharacterUIService provideCharacterService(Picasso picasso, NotificationUtil notificationUtil, ViewHolderFactor viewHolderFactor) {
        return new CharacterUIService(picasso, notificationUtil, viewHolderFactor);
    }
}

其中 CharacterUIService 是創建包含 ViewHolderFactory 的 RecyclerViewAdapter 新實例的類。

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

    // ...
}

我需要 ViewHolderFactor 的成員才能注入它。

我擔心需要創建新的全局變量並增加構造函數中傳遞的參數數量。 是否有更好的方法來注入這些子類,或者我可以將其視為允許單元測試的好方法嗎?

我可以將其視為允許單元測試的好習慣嗎?

首先——在我個人看來——我認為你做的測試過度了。 在您提供的測試用例中,您基本上是在測試android 框架本身 如果要測試工廠,則應測試返回的是小項還是大項,而不是視圖不為空。

但是,是的,您的方法似乎是允許單元測試的合理方法。

其中 CharacterUIService 是創建 RecyclerViewAdapter 新實例的類

您可能想過度考慮CharacterUIService的作用。 “創建一個新實例”聽起來像是應該由 dagger 處理的東西,因為您已經在使用它了。

還必須將持有實例的外部類注入工廠

為什么? 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

只是創建讓匕首創建該適配器?


通常,如果您支持構造函數注入,那么您可以刪除您的@Provides 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,因為你顯然把很多東西混在一起了。 好好看看構造函數注入並利用它,它可以為您節省大量工作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM