2015-04-03 33 views
12

Hançer 2'yi kullanarak, tek bir kapsamda birden çok konumda bir tekil nesneyi enjekte etmeye çalışıyorum. Ancak, çözümüm her seferinde yeni bir örnek oluşturuyor.Hançer 2 singleton çalışmıyor

Bu test projesinde, DaggerModule'ı başlatan bir MainActivity var. DaggerModule, Box'u Cat olarak parametre olarak alan Box ve Cat nesnelerini sağlar. Ayrıca, MainActivity'imdeki Cat'i de alıyorum. Son olarak, enjekte edilen her iki Cat değişkeninin referanslarını kontrol ediyorum (sırasıyla Kutu ve MainActivity'de), fakat aynı örnek değildir.

Bunun yerine MainCaitıcamda iki kez offerCat() öğesini çağırırsam, aynı örnek sağlanır.

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; 
    } 

} 

Şimdiden teşekkürler!

Düzenleme: provideBox yerine doğrudan provideBox içinden provideCat çağıran bir kedi argüman alır ve Kutusu oluşturmak için kullanır eğer çalışır . MainActivity içinde provideCat çağırmak ve DaggerModule içinde provideBox içinden bunu yapmak arasındaki fark nedir

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

vs

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

? Hançer derleyicisinin DaggerModule'i harici sınıflar ile aynı şekilde işlememesi ve buna ek olarak tekliflerim orada belirtilirse ek açıklamaların uygulanmaması olabilir mi?

cevap

6

ProvidBox içinden offerCat'i aramak istememin nedeni, Component arabirimindeki bir yanlış anlamadır. Bileşen arabiriminin gerçekten Modül tarafından uygulanmadığını yanlış anlamıştım, bu nedenle Modülün yöntemlerinin argümanlarının, Bileşenin ilgili yöntemlerinde beyan edilmesi gerekmiyordu. Durum böyle olsaydı, kaçınmak istediğim MainAktivite'nin ProvidBox yöntemi çağrısında Cat örneğini yaratmamı zorlaştırabilirdi (dolayısıyla, modülün sağlayıcısı olan box'ı doğrudan providCat yöntemiyle çağırıyordu). Aslında, Bileşen yöntemlerinde argümanları bildirmek, Dagger derleyicisini bile derleyemedi.

Ancak Bileşen yöntemleri bağımsız değişkenler almıyorsa, çözüm, gerektiğinde Modül yöntemlerinde argüman olarak örneklerin enjekte edilmesiydi (modülün kendisinden karşılık gelen sağlama yöntemlerini çağırmak yerine) ve yalnızca aramak zorunda kaldı MainActivity gelen komponente parametresiz yöntemleri aşağıdaki gibidir:

MainActivity:

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

Bileşen:

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

Modül: MainActivity ve 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); 
    } 

} 

Kedi tekil örnekleri şimdi aynıdır ve ben MainActivity onları beyan etmek yoktu, ama Hançer hepsini ele. Başarı! Yine de, yöntemlerin, harici sınıflar denildiğinde, modülün kendisinden farklı olarak neden farklı çalıştıklarından emin değilsiniz.

+2

Davranışın farklı olmasının nedeni, örnek yönetimin modül değil, bileşen uygulaması tarafından ele alınmasıdır. Yöntemi doğrudan çağırdığınızda, yalnızca başka bir Java yöntemi gibi adlandırılır, ancak bileşenlerin bağımlılıkları bir araya getirmesine izin verdiğinizde, yalnızca bir örnek olduğundan emin olmak için bir “dagger.internal.ScopedProvider” kullanır. – gk5885

+5

Ayrıca, @ Injected olan türler için, sınıfı (bu durumda 'Cat' ve' Box') doğrudan '@ Singleton'la ekleyebilir ve' @ Sağlar 'yöntemlerini tamamen kaldırabilirsiniz. – gk5885

+0

Bilgi ve bahşiş için teşekkürler! – Johe

İlgili konular