在Dagger2中,@ Singleton注释的目的是什么?

时间:2016-04-27 19:24:08

标签: 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;
    }
}

通过将@Singleton注释添加到provideCounter()方法,您是否指定只提供一个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注释会不合法吗?

1 个答案:

答案 0 :(得分:2)

@Singleton将确保组件中只有其中一种

所以是的,将它设置为singleton将导致在任何地方使用相同的对象使用此组件。如果您创建第二个组件,还将创建第二个计数器 - 它是一个不同的对象图。

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

这就是说,当我需要Counter名为buttonBCounter的方法调用此方法时,总是因为您的模块构造函数而返回相同的对象:

// 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将处理正确的对象缓存。

使用匕首,让匕首真正处理对象创建可能是一个好主意。

然后你可以继续做像......这样的事情。

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

...这将让你充分利用构造函数注入。如果参数发生变化,则无需更新参数。

如果有疑问,只需添加日志记录语句和/或附加调试器。没有太大的魔力,请继续尝试吧!