【问题标题】:How to inject into a java class that doesn't have any activity or fragment using dagger2如何使用 dagger2 注入没有任何活动或片段的 java 类
【发布时间】:2016-10-20 23:21:20
【问题描述】:
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);
    }
}

我的应用组件

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

非常感谢您的任何建议,

【问题讨论】:

    标签: android dependency-injection dagger-2


    【解决方案1】:

    Dagger-2 经常工作。因此,如果在Activity(或Fragment)对象内部注入了@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;
        }
    }
    

    然后一切都会被正确注入。

    为什么参数应该作为构造函数的参数传递给类?这样的设计模式符合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;
        }
    }
    

    【讨论】:

    • 正是我想要的......谢谢 Zag
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多