android - 如何使用 dagger2 注入(inject)没有任何 Activity 或 fragment 的 java 类

标签 android dependency-injection dagger-2

Android Studio 2.2.2

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

我想将改造服务注入(inject)到模型中。但是,由于 NewsListModelImp 不包含对上下文或 Activity 的任何引用,因此我无法调用 getApplication()。如果你在一个 Activity 或 fragment 中,你会做什么。我不想在 NewsListModeImp 的构造函数中传递任何上下文或 Activity ,因为它们必须来自演示者,我想避免那里有任何 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);
    }
}

我的应用组件

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

非常感谢您的任何建议,

最佳答案

Dagger-2反复工作。因此,如果在 Activity(或 Fragment)内部对象被注入(inject),并且它的构造函数被正确地注解为 @Inject 注释,构造函数的参数也将被注入(inject).

假设在您要注入(inject)的应用程序中:

@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;
    }
}

然后一切都将被正确注入(inject)。

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

额外信息:

可以注入(inject)实现特定接口(interface)的对象。描述了这种技术here .在您的情况下,NyTimesPresenter 可以具有 NewsListModelContract,因为它是依赖项而不是 NewsListModelImp。为此,请将另一个模块添加到您的 AppComponent:

@Singleton
@Component(
        modules = {
                RetrofitModule.class,
                AppModule.class
        })
public interface AppComponent {

AppComponent 提供具体类实现接口(interface)的方法应该如下所示:

@Singleton
@Module
public abstract class AppModule {

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

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

public class NyTimesPresenter {

    NewsListModelContract newsListModel;

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

关于android - 如何使用 dagger2 注入(inject)没有任何 Activity 或 fragment 的 java 类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40166022/

相关文章:

android - 加载程序在 Activity 启动时重新启动混淆

c#-4.0 - 将同一接口(interface)的不同实现和配置注入(inject)到不同的客户端

symfony - Symfony2 中的服务依赖注入(inject)

java - Dagger 2 : When to use constructor injections and when to use field injections?

android - 当 wifi SSID 改变时执行代码

java - 必须关闭并重新启动应用程序才能在 map 上显示正确的位置

java - 当屏幕旋转时,Android Activity 是如何重新创建的?

c# - 配置服务后访问身份密码选项

java - 了解 dagger2 ScopedProvider 中的延迟初始化单例,作者:Gregory Kick

android - Dagger 注入(inject)可以用静态方法完成吗?