Dagger 2创建单例实例 [英] Dagger 2 create singleton instance
问题描述
请考虑以下情形:我在Presenter A上调用Webservice,并将响应数据保存在同一Presenter上。我想在演示者E上使用相同的响应数据。但是我无法将响应对象传递给每个演示者B,C,D。因此,我尝试使用getter& amp;将我的响应对象存储在单独的Holder类中。二传手。我使用Dagger Inject构造函数注释初始化了Holder类,并尝试在Presenter E上使用它。但是我得到了空的回应而不是我的数据。有人能建议我以最好的方式处理这种情况吗?预先感谢
Consider the scenario that I am calling Webservice at Presenter A and holding the response data at the same Presenter. I want to utilize the same response data at Presenter E. But I cant pass the response object to each presenter B, C, D. So, I tried to store my response object at separate Holder class with getter & setter. I initialized Holder class using Dagger Inject constructor annotation and tried to consume it at Presenter E . But I got Empty response instead of my datas . Can any one suggest me to handle this scenario in best way . Thanks in advance
推荐答案
对于使用Dagger2的方式,您有很多基本问题,但我的时间有限,因此我暂时回答有关砂浆的问题-我只能说在某些设备上, getSystemService()
在 Application
而不是 onCreate()
,这意味着您应该像这样初始化根目录范围:
You have a lot of fundamental problems with how you're using Dagger2, but my time is limited, so I'll answer for the time being regarding Mortar - all I can say is that on some devices, getSystemService()
is called sooner in Application
than onCreate()
, which means you should initialize your root mortar scope like this:
@Override
public Object getSystemService(String name) {
if(rootScope == null) {
rootScope = MortarScope.buildRootScope()
.withService(InjectorService.TAG, new InjectorService(this))
.build("Root");
}
if(rootScope.hasService(name)) { // if the additional "Context" service is within Mortar
return rootScope.getService(name);
}
return super.getSystemService(name); // otherwise return application level context system service
}
我个人有这个 onCreate()
@Override
public void onCreate() {
super.onCreate();
Fabric.with(this, new Crashlytics());
realmHolder = new RealmHolder();
ApplicationHolder.INSTANCE.setApplication(this);
appConfig = new AppConfig(this);
InjectorService.obtain().inject(this); // <--- this one obtains component
initializeRealm();
}
在InjectorService中:
And in InjectorService:
public static ApplicationComponent obtain() {
return ((InjectorService) MortarScope.getScope(ApplicationHolder.INSTANCE.getApplication())
.getService(TAG)).getComponent();
}
因此,在最坏的情况下, getSystemService ()
在启动时或创建单例匕首组件时初始化了RootScope。
As such, in the worst case scenario, getSystemService()
initialized my RootScope either at start-up, or when the singleton dagger component was created.
该解决方案当前不是多进程的友好(因此Firebase崩溃报告会通过两次调用 CustomApplication
中的 onCreate()
杀死它)
This solution is currently not multi-process friendly (so Firebase Crash Reporting would kill it by calling onCreate()
in CustomApplication
twice)
编辑:喷射器服务代码
public class InjectorService {
public static final String TAG = "InjectorService";
private ApplicationComponent applicationComponent; //dagger2 app level component
InjectorService(CustomApplication customApplication) {
AppContextModule appContextModule = new AppContextModule(customApplication);
RealmModule realmModule = new RealmModule();
applicationComponent = DaggerApplicationComponent.builder()
.appContextModule(appContextModule)
.realmModule(realmModule)
.build();
}
public ApplicationComponent getInjector() { //return the app component to inject `this` with it
return applicationComponent;
}
public static InjectorService get(Context context) {
//this is needed otherwise the compiler is whining. -_-
//noinspection ResourceType
return (InjectorService) context.getSystemService(TAG);
}
public static ApplicationComponent obtain() {
return ((InjectorService) MortarScope.getScope(ApplicationHolder.INSTANCE.getApplication())
.getService(TAG)).getInjector();
}
}
至于最初的问题,这是因为您在构造函数中添加了 @Inject
批注,但并未在其上包含 @Singleton
类本身
As for your initial question, it's because you added @Inject
annotation to your constructor, but did not include @Singleton
on the class itself
@Singleton
public class Blah {
@Inject
public Blah() {
}
}
编辑:
我放假回家了,所以最初的错误是
I got home from vacation, so initial error is
错误:( 40,5)错误:com.hari.daggerpoc.application.App.Component的范围为
@ com.hari.daggerpoc.frameworks.dagger.DaggerScope可能未引用具有不同范围的
绑定:
@Singleton类com.hari.daggerpoc.cache.ResponseCache
Error:(40, 5) error: com.hari.daggerpoc.application.App.Component scoped with @com.hari.daggerpoc.frameworks.dagger.DaggerScope may not reference bindings with different scopes: @Singleton class com.hari.daggerpoc.cache.ResponseCache
在 App
:
@dagger.Component(modules = {Module.class})
@DaggerScope(Component.class)
public interface Component extends AppDependencies {
void inject(App app);
}
从此类继承而来:
@Module(includes = {Utils.class, ResponseCache.class})
public interface AppDependencies {
Utils utils();
ResponseCache responseCache();
}
...这完全不是模块,因此注释是不必要的,但是,嘿。
...which is totally NOT a module, so that annotation is unnecessary, but hey.
无论如何,问题 now 是,虽然依赖项是有作用域的,但它来自不同的作用域(我不知道不使用单例作用域),所以如果您进行更改
Anyways, the issue now is that while the dependency is scoped, it is from a different scope (I didn't know the singleton scope isn't used), so if you change
@Singleton
public class ResponseCache {
@Inject
public ResponseCache(){
}
@DaggerScope(App.Component.class)
public class ResponseCache {
@Inject
public ResponseCache(){
}
然后如果在 ScreenA
中您进行了更改
Then if in ScreenA
you change
public Callback<WeatherResponse> configServiceCallback = new Callback<WeatherResponse>() {
@Override
public void onResponse(Call<WeatherResponse> call, Response<WeatherResponse> response) {
Log.d("ScreenA","Response data -->"+response.body().toString());
Flow.get(context).setHistory(History.single(new ScreenB()), Flow.Direction.FORWARD);
responseCache.setWeatherResponse(response.body());
}
至
public Callback<WeatherResponse> configServiceCallback = new Callback<WeatherResponse>() {
@Override
public void onResponse(Call<WeatherResponse> call, Response<WeatherResponse> response) {
Log.d("ScreenA","Response data -->"+response.body().toString());
responseCache.setWeatherResponse(response.body());
Flow.get(context).setHistory(History.single(new ScreenB()), Flow.Direction.FORWARD);
}
然后说
08-28 18:12:48.369 31253-31253/com.hari.daggerpoc D/ScreenA: Response data -->WeatherResponse{endpoint=Endpoint{url='http://www.waynedgrant.com/weather/api/weather.json', version=1.7, githubProject='null', copyright='Copyright © 2016 Wayne D Grant (www.waynedgrant.com)'}}
08-28 18:12:48.369 31253-31253/com.hari.daggerpoc D/ScreenB: Response cache -->WeatherResponse{endpoint=Endpoint{url='http://www.waynedgrant.com/weather/api/weather.json', version=1.7, githubProject='null', copyright='Copyright © 2016 Wayne D Grant (www.waynedgrant.com)'}}
这篇关于Dagger 2创建单例实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!