考虑一下我在Presenter A上调用Webservice并在同一个Presenter中保存响应数据的场景。我想在Presenter E中使用相同的响应数据。但是我无法将响应对象传递给每个演示者B,C,D。因此,我试图将响应对象存储在单独的Holder类中,并使用getter & setter。我使用Dagger Inject构造函数注释初始化Holder类,并试图在Presenter E中使用它。但我得到空的回应,而不是我的数据。任何人都可以建议我以最好的方式处理这种情况。在此先感谢Dagger 2创建单例实例
回答
你的基本问题很多与您如何使用Dagger2,但我的时间是有限的,所以我会回答暂且关于砂浆 - 所有我能说的是,在某些设备上,getSystemService()
在Application
叫早于onCreate()
,这意味着你应该初始化根砂浆范围是这样的:
@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
}
Perso应受,我在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过这样的:
public static ApplicationComponent obtain() {
return ((InjectorService) MortarScope.getScope(ApplicationHolder.INSTANCE.getApplication())
.getService(TAG)).getComponent();
}
因此,在最坏的情况下,getSystemService()
在启动初始化我RootScope要么,或当单匕首组件已创建。
该解决方案是目前不支持多进程友好(所以火力地堡崩溃报告会通过调用CustomApplication
onCreate()
两次杀吧)
编辑:注入器服务代码
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
public class Blah {
@Inject
public Blah() {
}
}
编辑:
我回到家里休假,所以初始误差是
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();
}
...这完全不是一个模块,这样标注是不必要的,但嘿。
不管怎么说,这个问题现在为,虽然依赖的作用范围,它是从不同的范围(我不知道是不是使用单范围),所以如果你改变
@Singleton
public class ResponseCache {
@Inject
public ResponseCache(){
}
到
@DaggerScope(App.Component.class)
public class ResponseCache {
@Inject
public ResponseCache(){
}
然后如果ScreenA
你改变
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)'}}
如果我没有错,你正在返回应用程序组件在gets()方法,我直接注入。但是我很困惑你在哪里创建组件?其余部分与我的代码非常相似,因为你也只是在onCreate方法中注入组件。而且我试图在AppDependencies.class/Utils.class中添加Singleton注解。但是在编译时抛出错误“com.hari”。使用com.hari.daggerpoc.frameworks.dagger.DaggerScope作用域的daggerpoc.application.App.Component可能不会引用与不同作用域的绑定: 单例实用程序“ – Jeyahariprakash
”添加了“InjectorService”代码。 'new InjectorService(this)'在'withService()'中调用。 – EpicPandaForce
所以你应该把'@ Singleton'放在** ResponseCache **类 – EpicPandaForce
我可以想象这个解决方案,您的问题。
的一点是,你需要从主持人的ApiRequest
取出并使用interactor
中,演示者收到这个交互器在他的构造函数注入,在这种情况下,他们将共享相同的交互器实例(如果他是单身) 。如果您使用的是OkHttpClient
,则交互器负责执行缓存,您可以在不使用holder class
(由您决定)的情况下制作缓存,但在此解决方案中,您不会为相同数据执行2个API调用。
事情是这样的:
public class PresenterA(){
private UserInteractor userInteractor;
private ViewA view;
public PresenterA(UserInteractor interactor, ViewA view){
this.interactor = interactor;
this.view = view;
}
public void getUser(){
interactor.findFirst(new MyCallback(){
@Override
public void onSuccess(User user){
view.loadUserName(user.getName());
}
});
}
}
public class PresenterB(){
private UserInteractor userInteractor;
private ViewB view;
public PresenterA(UserInteractor interactor, ViewB view){
this.interactor = interactor;
this.view = view;
}
public void getUser(){
interactor.findFirst(new MyCallback(){
@Override
public void onSuccess(User user){
view.loadAddress(user.getAddress().getLine1());
}
});
}
}
public class UserInteractor(){
private MyHolderData holder;
private MyApi api;
public UserInteractor(MyHolderData holder, MyApi api){
this.holder = holder;
this.api = api;
}
public User getUser(){
if(holder.hasCache()){
return holder.getUser();
}
api.requestUser(new MyApiCallback(){
@Override
public void onSuccess(User user){
return user;
}
})
}
}
感谢您的回答。我正在使用OkHttpClient和Retrofit库。但我不想缓存我的Web服务的响应。假设,当我打开我的应用程序时,我需要在PresenterA上调用Sceen 1上的天气webservice,并且我想在PresenterD上显示天气细节,它出现在屏幕4上。因此,创建了一个单独的类来存储响应对象,并试图在其他屏幕上使用它。但它不能正常工作 – Jeyahariprakash
只需创建一个WebService响应的持有者并与您的演示者分享(如示例),如果您可以发布您的代码并提供可帮助的问题。 –
为了分享我的代码,我尝试创建示例项目。这次我在null对象引用上的''mortar.MortarScope mortar.MortarScope.findChild(java.lang.String)'上得到了空指针异常。我正试图解决这个问题。你有什么想法吗? – Jeyahariprakash
- 1. Spring创建单例的多个实例?
- 2. 创建实例
- 3. 创建实例
- 4. 创建实例
- 5. 在R中创建2个h2o实例
- 6. StructureMap创建实例
- 7. 创建EC2实例
- 8. GLTF创建实例
- 9. WebApplication有2个单例类的实例
- 10. GSON实例创建者创建的实例,但字段为空
- 11. Angular 2单页实例
- 12. 在BackgroundWorker中创建表单的实例
- 13. 如何单元测试实例创建?
- 14. 重新创建实体单例
- 15. ExtJS的4创建表单实例
- 16. 在Objective C中创建单例类的另一个实例
- 17. Javascript:自调用单例函数vs创建函数的实例?
- 18. 如何找到创建Java单例实例的位置?
- 19. 是否有可能从工厂创建单例实例
- 20. 如何创建依赖类的单例实例?
- 21. 创建资源实例?
- 22. 无法创建类实例
- 23. 从类名创建实例
- 24. 混淆创建类实例
- 25. 发布excel实例创建
- 26. AWS实例创建错误
- 27. 创建类的实例
- 28. 在哪里创建实例
- 29. 创建对象实例
- 30. CGLIB - 控制实例创建
您需要的范围'@ Singleton'添加到您的'@ Provides'的持有者批注的方法。 – EpicPandaForce
即使我尝试过SingleTon模式。它不适合我。我将把我的项目上传到GIT。我不知道我错过了什么。 – Jeyahariprakash
当我到达那里时,我会尝试着看看它 – EpicPandaForce