2015-04-03 74 views
12

用匕首2,我試圖注入在一個範圍內的多個位置的單個對象。但是,似乎我的解決方案每次都會創建一個新實例。匕首2單身不工作

在這個測試項目中,我有一個初始化DaggerModule一個MainActivity。 DaggerModule提供Box和Cat對象,Box以Cat作爲參數。我也在主動活動中接受貓。最後,我檢查注入的兩個Cat變量(分別在Box和MainActivity中)的引用,但它們不是同一個實例。

如果我在我的MainActivity中調用兩次provideCat(),則會提供相同的實例。

MainActivity:

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發生在貓參數,並使用它來創建箱,而不是從內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); 
    } 

什麼叫provideCat在MainActivity並在DaggerModule內provideBox從這樣做有什麼區別?難道Dagger編譯器不會像處理外部類一樣處理DaggerModule,如果我在那裏調用provideCat,則註釋不會被應用?

回答

6

我想從provideBox中調用provideCat的原因是我對Component接口的一個誤解。我誤解了Component接口實際上並未被Module實現,所以Module的方法的參數不必在Component的相應方法中聲明。如果是這樣,它會迫使我在MainActivity的provideBox方法調用中創建Cat實例,我想避免它(因此直接在Module的provideBox方法中調用provideCat)。實際上,在Component方法中聲明參數甚至使Dagger編譯器無法編譯。

但是由於Component方法不帶參數,因此解決方案只需在Module方法中根據需要插入實例作爲參數(而不是從Module內部調用相應的提供方法),只需調用從在MainActivity組件的參數的方法如下:

MainActivity:

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

組件:

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

模塊:

在MainActivity和Box的
@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聲明它們,但匕首處理這一切。成功!儘管如此,仍然不確定爲什麼提供方法在從外部類中調用時比從模塊本身中調用不同。

+2

行爲不同的原因是實例管理由組件實現處理,而不是模塊。當你直接調用方法時,它只會像調用其他任何Java方法一樣調用它,但是當你讓組件連接依賴時,它將使用'dagger.internal.ScopedProvider'來確保只有一個實例。 – gk5885 2015-04-08 22:50:07

+5

此外,對於'@Inject'ed類型,您可以直接使用'@ Singleton'註釋類(本例中爲Cat和Box),並避免使用@ @提供方法。 – gk5885 2015-04-08 22:51:41

+0

感謝您的信息和提示! – Johe 2015-04-10 20:39:13