9

मेरा प्रश्न this जैसा है।डैगर 2 (गतिविधि स्कोप के भीतर) के साथ कस्टम व्यू निर्भरता इंजेक्शन

public class CustomLiveData extends LiveData<SomeEvent> { 

    @Inject 
    public CustomLiveData(@ActivityContext Context context) { 
     //.... 
    } 

} 

है कि मैं एक कस्टम दृश्य में इंजेक्षन करना चाहते हैं:

:

public class CustomView extends View { 
    @Inject 
    SomeApplicationProvider anyProvider; 

    @Inject 
    CustomLiveData dataProvider; 
    // Getting @com.di.qualifiers.ActivityContext android.content.Context cannot be provided without an @Provides-annotated method. 
    // @com.di.qualifiers.ActivityContext android.content.Context is injected at com.repositories.CustomLiveData.<init>(context) 
    // com.repositories.CustomLiveData is injected at com.ui.CustomView.dataProvider com.ui.CustomView is injected at 
    // com.di.ApplicationComponent.inject(view) 

    public CustomView(Context context) { this(context, null); } 
    public CustomView(Context AttributeSet attrs) { 
     super(context, attrs); 

     // Works ok for application provider 
     Application.getComponent(context).inject(this); 
    } 
} 

और यहाँ डि वर्गों के बाकी है

तो उदाहरण के लिए, मैं एक LiveData कार्यान्वयन है

@ApplicationScope 
@Component(
     modules = {AndroidInjectionModule.class, 
       ActivityBuilder.class 
     }) 

public interface ApplicationComponent extends AndroidInjector<MyApp> { 

    void inject(MyApp application); 

    void inject(CustomView view); 

    @Component.Builder 
    abstract class Builder extends AndroidInjector.Builder<MyApp> { 

     public abstract ApplicationComponent build(); 
    } 
} 

@ActivityScope 
@Module (subcomponents = MainActivitySubcomponent.class) 
public abstract class ActivityBuilder { 

    @Binds 
    @IntoMap 
    @ActivityKey(MainActivity.class) 
    abstract AndroidInjector.Factory<? extends Activity> 
    bindActivityInjectorFactory(MainActivitySubcomponent.Builder builder); 

    //... 

} 


@Subcomponent(modules = {MainActivityModule.class}) 
public interface MainActivitySubcomponent extends AndroidInjector<MainActivity> { 

    @Subcomponent.Builder 
    abstract class Builder extends AndroidInjector.Builder<MainActivity> { 

    } 
} 

@ActivityScope 
@Module 
public class MainActivityModule { 

    @Provides 
    @ActivityContext 
    public Context provideActivityContext(MainActivity activity) { 
     return activity; 
    } 

    // Seems to be wrong or not enough!? 
    @Provides 
    public CustomLiveData provideCustomLiveData(@ActivityContext Context context) { 
     return new CustomLiveData(context); 
    } 
} 


@Qualifier 
public @interface ActivityContext{ 
} 

नोट, मुझेपर कोई कंपाइलर शिकायत नहीं मिलती हैको देखने के बजाय MainActivity में इंजेक्शन दिया गया है। धन्यवाद!

+0

क्या आपको 'कस्टम लाइवडाइट' को 'कस्टम' व्यू में इंजेक्शन देने पर कोई संकलन त्रुटि मिली? कृपया इसे अपने प्रश्न के साथ पोस्ट करें। –

+0

संदेश को कस्टम व्यू भाग में शामिल किया गया था। "// getting @ com.di.qualifiers.ActivityContext android.content.Context नहीं देख सकता ....." – sinek

+0

क्या आप '@ ActivityContext' पोस्ट कर सकते हैं? –

उत्तर

13

tl; डॉ कस्टम अंदर मॉडल परत निर्भरता इंजेक्षन मत करो View वस्तुओं

View की

उपवर्गों डैगर 2 इंजेक्शन के लिए अच्छा लक्ष्य नहीं हैं। View वस्तुओं को खींचा जाना है और अन्यथा नहीं, इसलिए नाम "दृश्य" है। View के लिए रचनाकारों को यह स्पष्ट करना चाहिए; वे XML में निर्दिष्ट विशेषताओं से View ऑब्जेक्ट्स को बढ़ाने के लिए डिज़ाइन किए गए हैं। दूसरे शब्दों में, View ऑब्जेक्ट को layout.xml फ़ाइल में निर्दिष्ट किया जाना चाहिए, जो जीवन चक्र में उपयुक्त बिंदु पर फुलाया गया है, और फिर findViewById(int id), Butterknife या डेटा बाइंडिंग का उपयोग करके प्राप्त किया जाना चाहिए। इस तरह, सर्वोत्तम कस्टम View ऑब्जेक्ट्स कोई निर्भरता नहीं लेते हैं।

यदि आप View और मॉडल परत से कुछ डेटा लिंक करना चाहते हैं, तो मानक पैटर्न RecyclerView और ListView के लिए एडाप्टर लिखना है। यदि यह संभव नहीं है, तो एक सेटर का उपयोग करना (उदा।, setData()) कन्स्ट्रक्टर में मॉडल परत से निर्भरता पारित करने या View के जीवन चक्र विधियों में से किसी एक से इंजेक्शन का अनुरोध करने के लिए बेहतर है।

यदि आप ऑब्जेक्ट को AndroidInjector कक्षा का उपयोग करके गतिविधि या टुकड़े के अंदर इंजेक्ट करते हैं तो सही Context आपको कुछ भी करने के बिना प्रदान किया जाएगा। यह आपकी टिप्पणी बताता है "अगर किसी भी कंपाइलर शिकायतें नहीं मिलती हैं तो कस्टमलाईडाटा को मुख्य रूप से दृश्य में इंजेक्शन दिया जाता है।"

एक बार जब आपने गतिविधि में LiveData ऑब्जेक्ट इंजेक्शन दिया है, तो अपने कस्टम View के साथ डेटा को जोड़ने के लिए उपरोक्त विधियों (एडाप्टर या एक सेटर) में से एक का उपयोग करें।

: गूगल एंड्रॉयड वास्तुकला उदाहरण here जहां मॉडल परत से तत्वों डैगर 2 का उपयोग इंजेक्ट किया जाता है और फिर एक ListViewfindViewById और setAdapter()

लिंक का उपयोग कर डैगर 2 मुद्दा जहां View वस्तुओं के इंजेक्शन चर्चा की है करने के लिए के साथ जुड़े देखें https://github.com/google/dagger/issues/720

1

आपका डैगर पदानुक्रम इस तरह दिखता है: appcomponent ->activitycomponent

आप दृश्य के अंदर गतिविधि context, कि appcomponent पर सीधे निर्भर करता है इंजेक्षन की कोशिश करो।

यह संभव नहीं है क्योंकि appcomponent में गतिविधि संदर्भ प्रदान करने वाला कोई तरीका नहीं है। इसके बजाय, अंदरूनी दृश्य, आपको गतिविधि पुनर्प्राप्त करनी चाहिए (उदाहरण के लिए getContext का उपयोग करके), activitycomponent निकालें और केवल तब CustomLiveData डालें।

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