Android Dagger 2构造函数注入在调用模块之前未发生

Android Dagger 2构造函数注入在调用模块之前未发生,android,dependency-injection,dagger-2,dagger,Android,Dependency Injection,Dagger 2,Dagger,我正在学习匕首2,正在开发一个应用程序。我有一个设置模块,它依赖于一个设置管理器,它依赖于一个共享首选项管理器。我的问题是,我的设置模块在被调用之前没有被注入设置管理器。该设置管理器需要一个SharedPrefsManager,它也不会被注入任何地方 我做错了什么 按依赖关系顺序排列的代码段: @Module public class SettingsModule { @Inject SettingsManager manager; @Provides @Time

我正在学习匕首2,正在开发一个应用程序。我有一个设置模块,它依赖于一个设置管理器,它依赖于一个共享首选项管理器。我的问题是,我的设置模块在被调用之前没有被注入设置管理器。该设置管理器需要一个SharedPrefsManager,它也不会被注入任何地方

我做错了什么

按依赖关系顺序排列的代码段:

@Module
public class SettingsModule {   
    @Inject SettingsManager manager;

    @Provides
    @TimeControl
    int[] provideResetTime(){
        return manager.getResetTime();
    }

    @Provides
    @ThemeControl
    int provideThemeID(){
        return manager.getTheme();
    }
}
取决于设置管理器:

public class SettingsManager{
    private SharedPreferencesManager manager;
    @Inject
    SettingsManager(SharedPreferencesManager manager){
        this.manager = manager;
    }
}
取决于共享首选项管理器:

public class SharedPreferencesManager {
    private static SharedPreferencesManager instance = null;
    public static SharedPreferencesManager getInstance(){return instance;}
    String prefsKey = "SHAREDPREFSKEY";
    SharedPreferences sharedPrefs = null;
    Context applicationContext = null;

    @Inject
    SharedPreferencesManager(@ApplicationContext Context applicationContext){
        this.prefsKey = prefsKey;
        this.applicationContext = applicationContext;
        sharedPrefs = applicationContext.getSharedPreferences(prefsKey,Context.MODE_PRIVATE);
        instance = this;
    }
}

我认为您不应该在模块中添加
@Inject
注释,因为它们被构建为创建依赖项并仅通过对象图或简单构造函数接收其他依赖项的注释


下面是一个示例,说明如何避免模块中的@Inject注释以及之后的构造函数

设置模块.java

@Module
public class SettingsModule {

    @Provides
    @TimeControl
    int[] provideResetTime(SettingsManager manager) {
        return manager.getResetTime();
    }

    @Provides
    @ThemeControl
    int provideThemeID(SettingsManager manager) {
        return manager.getTheme();
    }

    @Provides
    SettingsManager provideSettingsManager(SharedPreferencesManager sharedPreferencesManager) {
        return new SettingsManager(sharedPreferencesManager);
    }

    @Provides
    SharedPreferencesManager provideSharedPreferencesManager(@ApplicationContext Context context) {
        return new SharedPreferencesManager(context);
    }
}
public class SettingsManager {
    private SharedPreferencesManager manager;

    SettingsManager(SharedPreferencesManager manager) {
        this.manager = manager;
    }
}
public class SharedPreferencesManager {
    private static SharedPreferencesManager instance = null;
    private SharedPreferences sharedPrefs = null;
    String prefsKey = "SHAREDPREFSKEY";
    Context applicationContext = null;

    SharedPreferencesManager(Context applicationContext) {
        this.applicationContext = applicationContext;
        sharedPrefs = applicationContext.getSharedPreferences(prefsKey, Context.MODE_PRIVATE);
        instance = this;
    }

    public static SharedPreferencesManager getInstance() {
        return instance;
    }
}
SettingsManager.java

@Module
public class SettingsModule {

    @Provides
    @TimeControl
    int[] provideResetTime(SettingsManager manager) {
        return manager.getResetTime();
    }

    @Provides
    @ThemeControl
    int provideThemeID(SettingsManager manager) {
        return manager.getTheme();
    }

    @Provides
    SettingsManager provideSettingsManager(SharedPreferencesManager sharedPreferencesManager) {
        return new SettingsManager(sharedPreferencesManager);
    }

    @Provides
    SharedPreferencesManager provideSharedPreferencesManager(@ApplicationContext Context context) {
        return new SharedPreferencesManager(context);
    }
}
public class SettingsManager {
    private SharedPreferencesManager manager;

    SettingsManager(SharedPreferencesManager manager) {
        this.manager = manager;
    }
}
public class SharedPreferencesManager {
    private static SharedPreferencesManager instance = null;
    private SharedPreferences sharedPrefs = null;
    String prefsKey = "SHAREDPREFSKEY";
    Context applicationContext = null;

    SharedPreferencesManager(Context applicationContext) {
        this.applicationContext = applicationContext;
        sharedPrefs = applicationContext.getSharedPreferences(prefsKey, Context.MODE_PRIVATE);
        instance = this;
    }

    public static SharedPreferencesManager getInstance() {
        return instance;
    }
}
SharedReferencesManager.java

@Module
public class SettingsModule {

    @Provides
    @TimeControl
    int[] provideResetTime(SettingsManager manager) {
        return manager.getResetTime();
    }

    @Provides
    @ThemeControl
    int provideThemeID(SettingsManager manager) {
        return manager.getTheme();
    }

    @Provides
    SettingsManager provideSettingsManager(SharedPreferencesManager sharedPreferencesManager) {
        return new SettingsManager(sharedPreferencesManager);
    }

    @Provides
    SharedPreferencesManager provideSharedPreferencesManager(@ApplicationContext Context context) {
        return new SharedPreferencesManager(context);
    }
}
public class SettingsManager {
    private SharedPreferencesManager manager;

    SettingsManager(SharedPreferencesManager manager) {
        this.manager = manager;
    }
}
public class SharedPreferencesManager {
    private static SharedPreferencesManager instance = null;
    private SharedPreferences sharedPrefs = null;
    String prefsKey = "SHAREDPREFSKEY";
    Context applicationContext = null;

    SharedPreferencesManager(Context applicationContext) {
        this.applicationContext = applicationContext;
        sharedPrefs = applicationContext.getSharedPreferences(prefsKey, Context.MODE_PRIVATE);
        instance = this;
    }

    public static SharedPreferencesManager getInstance() {
        return instance;
    }
}
这样,您就可以将所有注入逻辑留给模块,而具体的类就不必担心注入类本身了

@Module
public class SettingsModule {   
    @Inject SettingsManager manager;

    @Provides
    @TimeControl
    int[] provideResetTime(){
        return manager.getResetTime();
    }

    @Provides
    @ThemeControl
    int provideThemeID(){
        return manager.getTheme();
    }
}
应该是

@Module
public class SettingsModule {   
    @Provides
    @TimeControl
    int[] resetTime(SettingsManager manager) {
        return manager.getResetTime();
    }

    @Provides
    @ThemeControl
    int themeId(SettingsManager manager) {
        return manager.getTheme();
    }
}
请注意,您的提供程序没有作用域,因此(AFAIK)每次获取
themeId()
的调用和获取
resetTime()
的调用都很可能创建一个新的
setingsmanager

因此,您可能希望在提供的类中放置
@Singleton

@Singleton
public class SharedPreferencesManager {
    private SharedPreferences sharedPrefs = null;
    String prefsKey = "SHAREDPREFSKEY";
    Context applicationContext = null;

    @Inject
    SharedPreferencesManager(Context applicationContext) {
        this.applicationContext = applicationContext;
        sharedPrefs = applicationContext.getSharedPreferences(prefsKey, Context.MODE_PRIVATE); // why isn' this in a module?
    }
}

@Singleton
public class SettingsManager{
    private SharedPreferencesManager manager;
    @Inject
    SettingsManager(SharedPreferencesManager manager){
        this.manager = manager;
    }
}

这里有一个小问题:在模块中,经理在哪里?我需要我的SettingsManager实际提供其中两个字段。我可以看到不在模块中使用@Inject的逻辑,但我需要在那里设置该字段。我仍然在思考这一切是如何工作的,我是否应该使用组件以某种方式将它们包装在一起?不,Dagger将自动构建对象图,以便在这一行中使用适当的SharedReferenceManager
ProvideSettings Manager(SharedReferenceManager SharedReferenceManager)
。每当您注入这些依赖项时,它将通过运行方法
providedSharedPreferencesManager
获得
SharedPreferencesManager
。我的意思是
@提供@TimeControl int[]provideResetTime(){return manager.getResetTime();}
。。。这取决于设置管理器。那就是经理的领域。啊,我现在明白了。感谢所有的帮助,仍然在学习他们希望您如何使用Dagger2。我认为如果@Inject注释不在模块中,他们会工作的,因为它创建了一个复杂且难以理解的对象图
SettingsModule
组件的范围是什么?