Dagger 2创建单例实例 [英] Dagger 2 create singleton instance

查看:73
本文介绍了Dagger 2创建单例实例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请考虑以下情形:我在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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆