如何使用dagger2注入没有任何活动或片段的Java类 [英] How to inject into a java class that doesn't have any activity or fragment using dagger2
问题描述
Android Studio 2.2.2
我有一个 NewsListModelImp
类是MVP中的模型。
I have a NewsListModelImp
class which is the model in the MVP.
我想将改造服务注入模型中。但是,由于 NewsListModelImp
不包含对上下文或活动的任何引用,因此无法调用 getApplication()
。如果您处于活动或片段中,该怎么办。我不想在 NewsListModeImp
的构造函数中传递任何上下文或活动,因为那必须来自演示者,并且我想避免在那里出现任何Android东西。
I want to inject my retrofit service into the model. However, as NewsListModelImp
doesn't contain any reference to a context or activity I cannot call getApplication()
. Which is what you would do if you were in a activity or fragment. I don't want to pass any context or activity in the constructor of NewsListModeImp
as that would have to come from the presenter and I want to avoid any android stuff there.
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
批注,构造函数的参数也将被注入。
Dagger-2
works reccurently. So if inside Activity
(or Fragment
) object is injected and it's constructor is properly annotated with @Inject
annotation, the constructor's parameters will be injected too.
假设您要在应用程序内部注入:
Suppose inside the application you would like to 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
进行注释:
NewsListModelImp
constructor must also be annotated with @Inject
:
public class NewsListModelImp implements NewsListModelContract {
NYTimesSearchService mNYTimesSearchService;
@Inject
public NewsListModelImp(NYTimesSearchService nYTimesSearchService) {
this.mNYTimesSearchService = nYTimesSearchService;
}
}
然后将正确注入所有内容。
Then everything will be injected properly.
为什么要将参数作为构造函数的参数传递给类?这种设计模式符合 SOLID原则
。对象依赖项被注入到对象中,而不是在对象内部创建,并且这样的代码易于测试(在测试中,依赖项可以替换,即用 Mock
's)
Why the parameters should be passed to class as constructors' parameters? Such design pattern conforms SOLID principles
. Object dependencies are injected into objects and not created inside it and such code is easily testable (in tests dependencies can be replaced ie. by Mock
's)
附加信息:
可以注入实现特定接口的对象。 此处描述了这种技术。在您的情况下, NyTimesPresenter
可以具有 NewsListModelContract
作为其依赖项,而不是 NewsListModelImp
。为此,向您的 AppComponent
中添加另一个模块:
It is possible to inject objects implementing specific interfaces. Such technique is described here. In your case NyTimesPresenter
can have NewsListModelContract
as it's dependency instead of NewsListModelImp
. To do this add another module to your 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的实现
应该更改(只是用它实现的接口替换具体的类):
The implementation of NyTimesPresenter
should change (just to replace concrete class with interface it implements):
public class NyTimesPresenter {
NewsListModelContract newsListModel;
@Inject
public NyTimesPresenter(NewsListModelContract newsListModel) {
this.newsListModel = newsListModel;
}
}
这篇关于如何使用dagger2注入没有任何活动或片段的Java类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!