2015-04-03 17 views
12

डैगर 2 का उपयोग करके, मैं एक सिंगल स्कोप में एकाधिक स्थानों पर सिंगलटन ऑब्जेक्ट इंजेक्ट करने की कोशिश कर रहा हूं। हालांकि, ऐसा लगता है कि मेरा समाधान हर बार एक नया उदाहरण बनाता है।डैगर 2 सिंगलेट्स काम नहीं कर रहे

इस परीक्षण प्रोजेक्ट में, मेरे पास मुख्य एक्टिविटी है जो डैगर मॉड्यूल को प्रारंभ करती है। डैगर मॉड्यूल ऑब्जेक्ट बॉक्स और बिल्ली प्रदान करता है, जिसमें बॉक्स ले जाने वाला बिल्ली पैरामीटर के रूप में होता है। मैं अपनी मुख्य गतिविधि में बिल्ली भी लेता हूं। अंत में, मैं इंजेक्शन वाले दोनों बिल्ली चर (क्रमशः बॉक्स में और मुख्य गतिविधि में) के संदर्भों की जांच करता हूं, लेकिन वे एक ही उदाहरण नहीं हैं।

यदि मैं इसके बजाय मेरी मुख्य क्रिया में दो बार प्रदान करता हूं, तो वही उदाहरण प्रदान किया जाता है।

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

बनाम

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

क्या MainActivity में provideCat बुला और DaggerModule में provideBox के भीतर से यह कर के बीच अंतर है? क्या यह हो सकता है कि डैगर कंपाइलर डैगर मॉड्यूल को बाहरी वर्गों के साथ समान तरीके से संसाधित नहीं करता है और अगर मैं वहां प्रदान करता हूं तो एनोटेशन लागू नहीं होते हैं?

उत्तर

6

कारण मैं प्रदान करना चाहता था प्रदान करने के लिए प्रदान करें बॉक्सबॉक्स घटक इंटरफ़ेस के मेरे हिस्से पर एक गलतफहमी थी। मुझे गलत समझा गया कि घटक इंटरफ़ेस वास्तव में मॉड्यूल द्वारा लागू नहीं किया गया था, इसलिए मॉड्यूल के तरीकों के तर्कों को घटक के संबंधित तरीकों में घोषित नहीं किया जाना था। अगर ऐसा होता, तो मुझे मुख्य एक्टिविटी के प्रदान करने के लिए बॉक्स विधि कॉल में बिल्ली उदाहरण बनाने के लिए मजबूर होना पड़ता था, जिसे मैं टालना चाहता था (इसलिए मॉड्यूल के प्रदान करने के लिए सीधे कॉलक को कॉल करना)। वास्तव में, घटक विधियों में तर्क घोषित करने से भी डैगर कंपाइलर संकलित करने में असमर्थ हो गया।

लेकिन चूंकि घटक विधियां तर्क नहीं लेती हैं, इसलिए समाधान केवल मॉड्यूल विधियों में तर्क के रूप में उदाहरणों को इंजेक्ट करने के लिए था (मॉड्यूल के भीतर से संबंधित उपलब्ध विधियों को कॉल करने के बजाय), और केवल कॉल करना MainActivity से घटक के parameterless तरीकों इस प्रकार है:

MainActivity:

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

घटक:

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

मॉड्यूल:

MainActivity और बॉक्स के
@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

व्यवहार अलग है कारण यह है कि उदाहरण प्रबंधन घटक कार्यान्वयन द्वारा मॉड्यूल नहीं है। जब आप सीधे विधि का आह्वान करते हैं, तो यह केवल इसे किसी भी अन्य जावा विधि की तरह कॉल करने जा रहा है, लेकिन जब आप घटक तार को एक साथ निर्भर करते हैं तो यह सुनिश्चित करने के लिए कि केवल एक उदाहरण है, यह 'dagger.internal.ScopedProvider' का उपयोग करेगा। – gk5885

+5

इसके अलावा, 'इंजेक्शन' वाले प्रकारों के लिए, आप सीधे '@ सिंगलटन' के साथ कक्षा (इस मामले में 'बिल्ली' और 'बॉक्स') को एनोटेट कर सकते हैं और' @ प्रोविड 'विधियों से पूरी तरह से बच सकते हैं। – gk5885

+0

जानकारी और टिप के लिए धन्यवाद! – Johe

संबंधित मुद्दे