Dagger2 中 @Scope
的作用其实很简单:用于保证被标记的 Component 一个实例在注入依赖时, 将标记了同样 Scope 注解的对象只注入同一个对象实例。
@Singleton 只是 Dagger2 预定义的注解。也就是说:如果一个 App 持有多个标记了 @Singleton 的 AppComponent, 这些 AppComponent 注入的对象不能保证是单例。 这也就是为什么需要在 Android 的 Application 类中持有唯一的 AppComponent。
下面是一个使用例:
- WaterPot 类为 App 的单例工具类。
- 每一个 Activity 持有自己的 ActivityComponent, 用于提供 Activity 范围内的同一个 VaseTable 实例。
- 一个 VaseTable 持有多个 Vase , Vase 持有 Flower 和 App 共享单例的 WaterPot。
import dagger.*;
import javax.inject.Inject;
import javax.inject.Scope;
import javax.inject.Singleton;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
class WaterPot {
private String name;
public WaterPot(String name) {
this.name = name;
System.out.println("[Create] WaterPot : " + name);
}
public String water() {
return "Water use: " + name;
}
}
class Flower {
private String name;
public Flower(String name) {
this.name = name;
System.out.println("[Create] Flower : " + name);
}
public String whisper() {
return name + " whisper";
}
}
class VaseTable {
public String name;
public VaseTable(String name) {
this.name = name;
System.out.println("[Create] VaseTable : " + name);
}
}
class Vase {
private Flower flower;
private WaterPot waterPot;
private VaseTable vaseTable;
@Inject
public Vase(Flower flower, WaterPot waterPot, VaseTable vaseTable) {
this.flower = flower;
this.waterPot = waterPot;
this.vaseTable = vaseTable;
System.out.println("[Create] Vase");
}
public String check() {
return "Table: " + vaseTable.name + ": " + waterPot.water() + " , and " + flower.whisper();
}
}
@Module
class AppModule {
static int count = 0;
@Provides @Singleton static WaterPot provideWaterPot() {
count ++;
return new WaterPot("WaterPot-" + count);
}
}
@Module
class FlowerModule {
static int count = 0;
@Provides static Flower provideFlower() {
count ++;
return new Flower("Flower-" + String.valueOf(count));
}
}
@Module
class ActivityRoomModule {
static int count = 0;
@Provides @ActivityRoomScope static VaseTable provideVaseTable() {
count ++;
return new VaseTable("VaseTable-" + String.valueOf(count));
}
}
@Scope
@Retention(RetentionPolicy.RUNTIME)
@interface ActivityRoomScope {
}
@Singleton
@Component(modules = {AppModule.class})
interface AppComponent {
void inject(App app);
WaterPot waterPot();
}
@ActivityRoomScope
@Component(dependencies = AppComponent.class, modules = {ActivityRoomModule.class, FlowerModule.class})
interface ActivityRoomComponent {
void inject(ActivityRoom activityRoom);
}
class ActivityRoom {
@Inject Vase vaseA;
@Inject Vase vaseB;
@Inject WaterPot waterPot;
ActivityRoom() {
ActivityRoomComponent activityRoomComponent = DaggerActivityRoomComponent.builder().appComponent(App.application.appComponent).build();
activityRoomComponent.inject(this);
}
public void show() {
System.out.println(vaseA.check());
System.out.println(vaseB.check());
System.out.println();
}
}
public class App {
public static App application;
public AppComponent appComponent;
@Inject WaterPot waterPot;
App() {
appComponent = DaggerAppComponent.create();
appComponent.inject(this);
}
public void run() {
System.out.println("App run..");
// Room A B share WaterPot
// Room A B have their own VaseTable
ActivityRoom roomA = new ActivityRoom();
roomA.show();
ActivityRoom roomB = new ActivityRoom();
roomB.show();
System.out.println(waterPot.water());
}
public static void main(String[] args) {
application = new App();
application.run();
}
}
输出结果
[Create] WaterPot : WaterPot-1
App run..
[Create] Flower : Flower-1
[Create] VaseTable : VaseTable-1
[Create] Vase
[Create] Flower : Flower-2
[Create] Vase
Table: VaseTable-1: Water use: WaterPot-1 , and Flower-1 whisper
Table: VaseTable-1: Water use: WaterPot-1 , and Flower-2 whisper
[Create] Flower : Flower-3
[Create] VaseTable : VaseTable-2
[Create] Vase
[Create] Flower : Flower-4
[Create] Vase
Table: VaseTable-2: Water use: WaterPot-1 , and Flower-3 whisper
Table: VaseTable-2: Water use: WaterPot-1 , and Flower-4 whisper
Water use: WaterPot-1