android - 在Dagger2中,@Singleton注解的用途是什么?

标签 android singleton dagger-2

假设我们有一个类Counter:

public class Counter {
    private int count;

    public Counter() {
        count = 0;
    }

    public int getCount() {
        return count;
    }

    public void count() {
        count++;
    }
}

还有一个提供计数器的ApplicationModule:

@Module
public class ApplicationModule {
    private Context context;
    private Counter counter;

    public ApplicationModule(Context context) {
        this.context = context;
        counter = new Counter();
    }

    @Provides @Singleton
    public Counter provideCounter() {
        return counter;
    }
}

通过向 provideCounter() 方法添加 @Singleton 注释,您是否指定仅提供一个 Counter 对象?

如果我们提供两个 Counter 对象:

@Module
public class ApplicationModule {
    private Context context;
    private Counter numberOfTimesButtonAWasPressed;
    private Counter numberOfTimesButtonBWasPressed;

    public ApplicationModule(Context context) {
        this.context = context;
        numberOfTimesButtonAWasPressed = new Counter();
        numberOfTimesButtonBWasPressed = new Counter();
    }

    @Provides @Named("buttonACounter")
    public Counter provideButtonACounter() {
        return numberOfTimesButtonAWasPressed;
    }

    @Provides @Named("buttonBCounter")
    public Counter provideButtonBCounter() {
        return numberOfTimesButtonBWasPressed;
    }
}

@Singleton 注释会非法吗?

最佳答案

@Singleton 将确保组件中只有同类之一

所以,是的,将其设置为单例将导致使用此组件的任何地方都使用相同的对象。如果您创建第二个组件,也会创建第二个计数器——它是一个不同的对象图。

@Provides @Named("buttonBCounter")
public Counter provideButtonBCounter() {
    return numberOfTimesButtonBWasPressed;
}

这就是说,当我需要一个名为 buttonBCounterCounter 时,调用此方法,但是由于您的模块,总是会返回相同的对象构造函数:

// don't do this.
public ApplicationModule(Context context) {
    numberOfTimesButtonAWasPressed = new Counter();
    numberOfTimesButtonBWasPressed = new Counter();
}

即使您没有使用 @Singleton 注释它,此方法也会像以前一样起作用,因为您将对象保留在模块中并返回相同的实例每次通话。

// do it right
@Singleton @Provides @Named("buttonBCounter")
public Counter provideButtonBCounter() {
    return new Counter();
}

这与上面的代码具有相同的效果,尽管该方法只会被调用一次,然后 dagger 将处理适当的对象缓存。

使用 dagger,真正让 dagger 负责对象创建可能是一个好主意。

然后您甚至可以继续做类似的事情

// if you have an @Inject annotated constructor
@Singleton @Provides @Named("buttonBCounter")
public Counter provideButtonBCounter(Counter counter) {
    return counter;
}

...这将使您充分利用构造函数注入(inject)。如果参数发生变化,无需更新。

此外,如果有疑问,只需添加日志记录语句和/或附加调试器。它没有什么魔力,快来尝试一下吧!

关于android - 在Dagger2中,@Singleton注解的用途是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36899111/

相关文章:

java - 如何修剪字符串中两个或三个逗号之后的字符串

java - 安卓屏幕上半部分的谷歌地图 V2 和安卓屏幕下半部分的 ListView

java - 数据库的单例模式。

java - 使用 Spring 框架单例 bean 进行单元测试

android - 如何在支持 SavedStateHandle 的 AndroidViewModel 中注入(inject)依赖项?

java - 如何使用选择器语法 Jsoup 通过 ID 的子字符串查找元素?

安卓 : How to calculate aspect ratio of images?

PHP 单例 : not holding instance

java - Dagger 2 ViewModelProvider.Factory 多次绑定(bind)

java - 无法在 Java Android 中使用 dagger2 在 fragment 中注入(inject)依赖项