使用Dagger 2,我试图在单个范围内的多个位置注入单例对象.但是,似乎我的解决方案每次都创建一个新的实例.
在这个测试项目中,我有一个MainActivity来初始化DaggerModule. DaggerModule提供对象Box和Cat,Box以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()); }
VS
// Works,same singleton injected. @Provides @Singleton public Box provideBox(Cat cat) { return new Box(cat); }
在MainActivity中调用provideCat并在DaggerModule中的provideBox中进行调用有什么区别?可能是Dagger编译器不像处理外部类一样处理DaggerModule,并且如果我在那里调用provideCat,那么注释不会被应用?
解决方法
我想要从offerBox中调用provideCat的原因是对我部分Component界面的误解.我误解了组件接口实际上没有被Module实现,所以Module的方法的参数不必在Component的相应方法中被声明.如果是这样,那么这样做会迫使我在MainActivity的provideBox方法调用中创建Cat实例,我想避免(因此直接在module的provideBox方法中调用provideCat).实际上,在Component方法中声明参数甚至使Dagger编译器无法编译.
但是由于Component方法没有引用参数,所以解决方案只是将实例作为参数在需要的Module方法中进行注入(而不是从Module中调用相应的提供方法),而只需调用Component的无参数方法从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处理了这一切.成功!仍然不知道为什么提供方法在外部类调用时的工作方式不同于模块本身.