考慮一下我在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. android.app.Application單例實例被重新創建
- 2. 工廠方法創建單例實例
- 3. Spring創建單例的多個實例?
- 4. 創建實例
- 5. 創建實例
- 6. 創建實例
- 7. 如何告訴Dagger 2根據X實例化哪個實現?
- 8. 提供並注入兩個不同實現的實例 - Dagger 2
- 9. 在R中創建2個h2o實例
- 10. GLTF創建實例
- 11. 實例創建(JS)
- 12. 創建EC2實例
- 13. StructureMap創建實例
- 14. 創建此實例
- 15. WebApplication有2個單例類的實例
- 16. GSON實例創建者創建的實例,但字段爲空
- 17. Angular 2單頁實例
- 18. 創建單例類
- 19. 如何單元測試實例創建?
- 20. ExtJS的4創建表單實例
- 21. 重新創建實體單例
- 22. 在BackgroundWorker中創建表單的實例
- 23. 創建多個表單實例
- 24. 知道何時通過創建子類創建類的實例?
- 25. Javascript:自調用單例函數vs創建函數的實例?
- 26. 如何使用MEF爲每個線程創建單例實例
- 27. 如何找到創建Java單例實例的位置?
- 28. javascript單例模式 - 創建不同實例的問題
- 29. 如何創建依賴類的單例實例?
- 30. 是否有可能從工廠創建單例實例
您需要的範圍'@ Singleton'添加到您的'@ Provides'的持有者批註的方法。 – EpicPandaForce
即使我嘗試過SingleTon模式。它不適合我。我將把我的項目上傳到GIT。我不知道我錯過了什麼。 – Jeyahariprakash
當我到達那裏時,我會嘗試着看看它 – EpicPandaForce