匕首 2 单例不起作用

使用 Dagger 2,我尝试在单个作用域中的多个位置注入单例对象。但是,似乎我的解决方案每次都会创建一个新实例。

在这个测试项目中,我有一个初始化DaggerModule的MainActivity。DaggerModule提供对象Box和Cat,Box将Cat作为参数。我也在我的主要活动中接受Cat。最后,我检查了注入的两个Cat变量的引用(分别在Box和MainActivity中),但它们不是同一个实例。

如果我在我的 MainActivity 中调用 provideCat() 两次,则会提供相同的实例。

主要活动:

public class MainActivity extends ActionBarActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        DaggerModule daggerModule = new DaggerModule();
        DaggerComponent daggerComponent = Dagger_DaggerComponent.builder()
                .daggerModule(daggerModule).build();

        // Same Cat instance returned.
        Cat cat1 = daggerComponent.provideCat();
        Cat cat2 = daggerComponent.provideCat();
        Log.d("=== cat1: ", cat1.toString());
        Log.d("=== cat2: ", cat2.toString());

        // Different Cat instance returned. Why?
        Box box = daggerComponent.provideBox();
        Log.d("=== box cat: ", box.getCat().toString());
    }
}

@Module
public class DaggerModule {

    @Provides
    @Singleton
    public Cat provideCat() {
        return new Cat();
    }

    @Provides
    @Singleton
    public Box provideBox() {
        return new Box(provideCat());
    }

}

@Singleton
@Component(modules = { DaggerModule.class })
public interface DaggerComponent {

    Cat provideCat();

    Box provideBox();

}

public class Cat {

    @Inject
    public Cat() {
    }

}

public class Box {

    private Cat mCat;

    @Inject
    public Box(Cat cat) {
        mCat = cat;
    }

    public Cat getCat() {
        return mCat;
    }

}

提前致谢!

编辑:如果 provideBox 采用 Cat 参数并使用它来创建 Box,而不是直接从 provideBox 中调用 provideCat,则此方法有效。

    // Doesn't work, new Cat instance created.
    @Provides
    @Singleton
    public Box provideBox() {
        return new Box(provideCat());
    }

    // Works, same singleton injected.
    @Provides
    @Singleton
    public Box provideBox(Cat cat) {
        return new Box(cat);
    }

在 MainActivity 中调用 provideCat 和在 DaggerModule 中从 provideBox 中执行此操作有什么区别?可能是Dagger编译器处理DaggerModule的方式与处理外部类的方式不同,并且如果我在其中调用proverCat,则不会应用注释?


答案 1

我想从 provideBox 内部调用 provideCat 的原因是我对 Component 接口的误解。我误解了组件接口实际上不是由模块实现的,因此模块方法的参数不必在组件的相应方法中声明。如果是这样的话,它将迫使我在MainActivity的provodBox方法调用中创建Cat实例,我想避免这种情况(因此直接在模块的provatherBox方法中调用provatherCat)。实际上,在 Component 方法中声明参数甚至使 Dagger 编译器无法编译。

但是,由于组件方法不采用参数,因此解决方案只是在需要时将实例作为参数注入模块方法中(而不是从模块本身内部调用相应的提供方法),并且只需要从 MainActivity 调用组件的无参数方法,如下所示:

主要活动:

Cat cat = daggerComponent.provideCat();
Box box = daggerComponent.provideBox();

元件:

Cat provideCat();
Box provideBox(); <- no arguments

模块:

@Module
public class DaggerModule {

    @Provides
    @Singleton
    public Cat provideCat() {
        return new Cat();
    }

    @Provides
    @Singleton
    public Box provideBox(Cat cat) { <- arguments
        return new Box(cat);
    }

}

MainActivity 和 Box 的 Cat 单例实例现在是相同的,我不必从 MainActivity 声明它们,但 Dagger 处理了这一切。成功!但是,仍然不确定为什么从外部类调用时,提供方法的工作方式与从模块本身调用时的工作方式不同。


答案 2

推荐