Dagger 2创建单例实例

时间:2016-08-17 12:53:19

标签: android dagger-2

考虑我在Presenter A上调用Webservice并在同一个Presenter上保存响应数据的场景。我想在Presenter E上使用相同的响应数据。但我不能将响应对象传递给每个演示者B,C,D。所以,我试图将我的响应对象存储在具有getter&的单独的Holder类中。二传手。我使用Dagger Inject构造函数注释初始化Holder类,并尝试在Presenter E中使用它。但我得到空响应而不是我的数据。任何人都可以建议我以最佳方式处理这种情况。提前致谢

2 个答案:

答案 0 :(得分:1)

我可以想象这个问题的解决方案。

关键是,您需要从演示者中删除ApiRequest并使用interactor,两个演示者都会在其构造函数中接收此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;
            }
        })
    }

}

答案 1 :(得分:1)

你对如何使用Dagger2存在很多基本问题,但我的时间有限,所以我暂时回答有关Mortar的问题 - 我只能做比如说在某些设备上,getSystemService()的{​​{1}}早于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 }

中有这个
onCreate()

在InjectorService中:

@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();
}

因此,在最坏的情况下,public static ApplicationComponent obtain() { return ((InjectorService) MortarScope.getScope(ApplicationHolder.INSTANCE.getApplication()) .getService(TAG)).getComponent(); } 在启动时或者在创建单例匕首组件时初始化了我的RootScope。

此解决方案目前不具备多进程友好性(因此Firebase崩溃报告会通过在getSystemService()中调用onCreate()两次来杀死它)

编辑:注射器服务代码

CustomApplication

至于您的初始问题,是因为您在构造函数中添加了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

修改

我从假期回家,所以最初的错误是

  

错误:(40,5)错误:com.hari.daggerpoc.application.App.Component作用域   @ com.hari.daggerpoc.frameworks.dagger.DaggerScope可能无法参考   具有不同范围的绑定:   @Singleton class com.hari.daggerpoc.cache.ResponseCache

它引用@Singleton public class Blah { @Inject public Blah() { } } 中的这个类:

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);
        }