如何使用dagger2注入没有任何活动或片段的java类

时间:2016-10-20 23:21:20

标签: android dependency-injection dagger-2

Android Studio 2.2.2

我有一个NewsListModelImp类,它是MVP中的模型。

我想将改装服务注入模型中。但是,由于NewsListModelImp不包含对上下文或活动的任何引用,因此我无法调用getApplication()。如果您在活动或片段中,您将采取以下措施。我不想在NewsListModeImp的构造函数中传递任何上下文或活动,因为它必须来自演示者,我想避免那里的任何android东西。

public class NewsListModelImp implements NewsListModelContract {
    @Inject
    NYTimesSearchService mNYTimesSearchService;

    public NewsListModelImp() {
        ((NYTimesSearchApplication)getApplication()).getAppComponent().inject(this);
    }
}

我的申请类

public class NYTimesSearchApplication extends Application {
    private AppComponent mAppComponent;

    public void onCreate() {
        super.onCreate();

        /* Setup dependency injection */
        createAppComponent();
    }

    private void createAppComponent() {
        mAppComponent = DaggerAppComponent
                .builder()
                .retrofitModule(new RetrofitModule())
                .build();
    }

    public AppComponent getAppComponent() {
        return mAppComponent;
    }
}

我提供的模块

@Module
public class RetrofitModule {
    private Retrofit retrofit() {
        return new Retrofit
                .Builder()
                .baseUrl(Constants.BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .build();
    }

    @Provides
    @Singleton
    public NYTimesSearchService providesNYTimesSearch() {
        return retrofit().create(NYTimesSearchService.class);
    }
}

我的App组件

@Singleton
@Component(modules = {RetrofitModule.class})
public interface AppComponent {
    void inject(NewsListModelImp target);
}

非常感谢任何建议,

1 个答案:

答案 0 :(得分:5)

Dagger-2重新开始工作。因此,如果注入了Activity(或Fragment)对象,并且使用@Inject注释正确地注释了它的构造函数,那么构造函数的参数也将被注入。 / p>

假设您想要注入的应用程序内部:

@Inject NyTimesPresenter presenter;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    ((NYTimesSearchApplication) getApplication()).getAppComponent().inject(this);
}

NyTimesPresenter的构造函数必须使用@Inject注释:

public class NyTimesPresenter {

    NewsListModelImp newsListModel;

    @Inject
    public NyTimesPresenter(NewsListModelImp newsListModel) {
        this.newsListModel = newsListModel;
    }
}

NewsListModelImp构造函数也必须使用@Inject注释:

public class NewsListModelImp implements NewsListModelContract {

    NYTimesSearchService mNYTimesSearchService;

    @Inject
    public NewsListModelImp(NYTimesSearchService nYTimesSearchService) {
        this.mNYTimesSearchService = nYTimesSearchService;
    }
}

然后一切都会正确注入。

为什么参数应该作为构造函数传递给类'参数?这种设计模式符合SOLID principles。对象依赖项被注入到对象中而不是在其中创建,并且这样的代码很容易测试(在测试中,依赖项可以被替换,即Mock' s)

额外信息:

可以注入实现特定接口的对象。描述了这种技术here。在您的情况下,NyTimesPresenter可以NewsListModelContract作为依赖,而不是NewsListModelImp。为此,请在AppComponent添加另一个模块:

@Singleton
@Component(
        modules = {
                RetrofitModule.class,
                AppModule.class
        })
public interface AppComponent {
提供具体类实现接口的

AppComponent方法应如下所示:

@Singleton
@Module
public abstract class AppModule {

    @Binds
    public abstract NewsListModelContract provideNewsListModelContract(NewsListModelImp newsListModelImp);
}

NyTimesPresenter的实现应该改变(只是用它实现的接口替换具体类):

public class NyTimesPresenter {

    NewsListModelContract newsListModel;

    @Inject
    public NyTimesPresenter(NewsListModelContract newsListModel) {
        this.newsListModel = newsListModel;
    }
}