2015-04-23 14 views
7

मुझे http://konmik.github.io/snorkeling-with-dagger-2.html पर आधारित एक साधारण डैगर 2 परीक्षण-सेटअप मिला है। यह एक वरीयता पत्रक इंजेक्ट करता है जो सभी प्राथमिकताओं को आउटपुट करता है। इंजेक्शन कक्षा में, मैं अधिक कक्षाओं को इंजेक्ट कर सकता हूं।डैगर 2 और इंटरफ़ेस कार्यान्वयन

public class MainActivity extends Activity { 
    @Inject PreferencesLogger logger; 
    @Inject MainPresenter presenter; 

    @Override protected void onCreate(Bundle savedInstanceState) { 
    MyApplication.getComponent().inject(this); 
    presenter.doStuff(); 
     logger.log(this); 
    } 
} 


public class PreferencesLogger { 

    @Inject OkHttpClient client; 
    @Inject public PreferencesLogger() {} 

    public void log(Contect context) { 
    // this.client is available 
    } 
} 

जब मैं इस चलाने के लिए, लकड़हारा सेट कर दिया जाता है, और PreferencesLogger.log अंदर OkHttpClient ठीक से सेट है। तो यह उदाहरण अपेक्षा के अनुसार काम करता है। अब मैं जगह पर एक एमवीपी संरचना प्राप्त करने की कोशिश कर रहा हूं। कार्यान्वयन के साथ एक मुख्य प्रतिनिधि इंटरफ़ेस है। MainActivity में मैं सेट एक:

@Inject MainPresenter presenter; 

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

public interface MainPresenter { 
    void doStuff(); 
} 

public class MainPresenterImpl implements MainPresenter { 

    @Inject OkHttpClient client; 

    public MainPresenterImpl() {} 

    @Override public void doStuff() { 
    // this.client is not available  
    } 
} 


@Module public class MainActivityModule { 
    @Provides MainPresenter provideMainPresenter() { 
     return new MainPresenterImpl(); 
    } 
} 

अब एक समस्या यह होती है कि OkHttpClient अब इंजेक्शन नहीं दिया गया है। मैं मॉड्यूल को पैरामीटर OkHttpClient स्वीकार करने के लिए बदल सकता हूं, लेकिन मुझे नहीं लगता कि यह करने का सुझाव दिया गया तरीका है। क्या कोई कारण है कि MainPresenterImpl सही ढंग से इंजेक्ट नहीं करता है?

+0

मैं यहाँ एक संबंधित प्रश्न पूछा: http://stackoverflow.com/questions/30555285/dagger2-injecting-implementation-classes-with-component – EpicPandaForce

+0

इस लेख और नमूना परियोजना जो मदद कर सकता है पर एक नज़र डालें: https://medium.com/@m_mirhoseini/yet-another-mvp-article-part-1-lets-get-to-now-the-project-d3fd553b3e21#.6y9ze7e55 –

उत्तर

4

कन्स्ट्रक्टर इंजेक्शन के विपरीत, @Inject@Provides विधियों में निर्मित निर्भरताओं के एनोटेटेड फ़ील्ड स्वचालित रूप से इंजेक्शन नहीं दिए जा सकते हैं। खेतों को इंजेक्ट करने में सक्षम होने के लिए एक घटक की आवश्यकता होती है जो क्षेत्र के प्रकार को अपने मॉड्यूल में प्रदान करती है, और प्रदाता विधियों में स्वयं, ऐसे कार्यान्वयन उपलब्ध नहीं है।

जब presenter फ़ील्ड MainActivity में इंजेक्शन दिया गया है, तो ऐसा होता है कि प्रदाता विधि कहा जाता है और presenter इसके वापसी मूल्य पर सेट होता है। आपके उदाहरण में, नो-Args कन्स्ट्रक्टर कोई प्रारंभिकता नहीं करता है, और न ही प्रदाता विधि करता है, इसलिए कोई प्रारंभिकता नहीं होती है।

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

कारण यह वर्तमान में एक त्रुटि फेंक नहीं है क्योंकि MainPresenterImpl मिल सकता है अपने OkHttpClient निर्भरता संतुष्ट करता है, तो MainPresenterImpl और नहीं MainPresenter कहीं इंजेक्शन के लिए एक लक्ष्य था। डैगर इंटरफ़ेस प्रकार के लिए सदस्यों-इंजेक्शन विधि नहीं बना सकता है, क्योंकि एक इंटरफ़ेस के रूप में, इसमें इंजेक्शन योग्य फ़ील्ड नहीं हो सकते हैं, और यह स्वचालित रूप से कार्यान्वयन प्रकार के फ़ील्ड को इंजेक्ट नहीं करेगा, क्योंकि यह केवल प्रदाता विधि की आपूर्ति कर रहा है रिटर्न।

4

आप कन्स्ट्रक्टर इंजेक्शन का उपयोग करके अपने MainPresenterImpl इंजेक्ट करने में सक्षम हो सकते हैं।

/* unscoped */ 
public class MainPresenterImpl implements MainPresenter { 

    @Inject 
    OkHttpClient client; 

    @Inject 
    public MainPresenterImpl() { 
    } 

    @Override public void doStuff() { 
     // this.client is now available! :) 
    } 
} 


@Module 
public class AppModule { 
    private MyApplication application; 

    public AppModule(MyApplication application) { 
     this.application = application; 
    } 

    @Provides 
    /* unscoped */ 
    public MyApplication application() { 
     return application; 
    } 
} 

@Module 
public abstract class MainActivityModule { 
    @Binds public abstract MainPresenter mainPresenter(MainPresenterImpl mainPresenterImpl); 
} 
संबंधित मुद्दे