2017-12-06 46 views
7

पर गतिविधि प्रदान करता है मैं ActivityModule को लागू करने के लिए एक कम बॉयलरप्लेट-वाई तरीका जानने की कोशिश कर रहा हूं जिसका उपयोग मेरी सभी ऐप गतिविधियों में किया जाता है।डैगर 2 योगदान एंड्रॉइड इंजेक्टर मॉड्यूल

ActivityModule:

@Module 
class ActivityModule(private val activity: Activity) { 

    @Provides @ActivityScope 
    fun providesActivity(): Activity = activity 

    @Provides @ActivityContext @ActivityScope 
    fun providesContext(): Context = activity 

    @Provides @ActivityContext @ActivityScope 
    fun providesLayoutInflater(): LayoutInflater = activity.layoutInflater 

    @Provides @ActivityContext @ActivityScope 
    fun providesResources(): Resources = activity.resources 

} 

AppActivityModule (AndroidInjectionModule के लिए गतिविधियों प्रदान करता है)

@Module(subcomponents = [ 
     AppActivityModule.WelcomeActivityComponent::class 
    ]) 
    internal abstract class AppActivityModule { 

     @Binds 
     @IntoMap 
     @ActivityKey(WelcomeActivity::class) 
     abstract fun bindWelcomeActivityInjectorFactory(builder: WelcomeActivityComponent.Builder): AndroidInjector.Factory<out Activity> 

     @ActivityScope 
     @Subcomponent(modules = [(ActivityModule::class)]) 
     interface WelcomeActivityComponent : AndroidInjector<WelcomeActivity> { 
     @Subcomponent.Builder abstract class Builder : AndroidInjector.Builder<WelcomeActivity>() { 
      abstract fun activityModule(myActivityModule: ActivityModule): AndroidInjector.Builder<WelcomeActivity> 

      override fun seedInstance(instance: WelcomeActivity) { 
       activityModule(ActivityModule(instance)) 
      } 
     } 
    } 
} 

क्या मैं AppActivityModule बजाय होना चाहता हूँ है:

@Module 
internal abstract class AppActivityModule { 
    @ContributesAndroidInjector(modules = [(ActivityModule::class)]) 
    abstract fun contributeWelcomeActivityInjector(): WelcomeActivity 
} 
यह मेरा मौजूदा सेटअप है

लेकिन यह काफी समझ में आता है, मुझे एक त्रुटि देता है /di/AppActivityModule_ContributeWelcomeActivityInjector.java:29: error: @Subcomponent.Builder is missing setters for required modules or subcomponents: [...di.modules.ActivityModule]

मेरा प्रश्न है - क्या मैं ऐसा करने की कोशिश कर रहा हूं जो हासिल करने के लिए एक कम बॉयलरप्लेट-वाई तरीका है? मुझे @Bind और @BindsInstance (this answer से) पता है, लेकिन ऐसा लगता है कि यदि मेरे पास मॉड्यूल-प्रति गतिविधि है और कंक्रीट गतिविधि प्रकार को बांधें जो मुझे इस मामले में नहीं चाहिए - मुझे ActivityModule सभी गतिविधियों के साथ काम करने के लिए चाहिए।

उत्तर

3

बॉयलरप्लेट को कम करने का एक तरीका एक सामान्य गतिविधि मॉड्यूल बनाना है और फिर प्रति गतिविधि एक छोटा विशिष्ट मॉड्यूल बनाना है। मेरी Kotlin अनुभवहीनता माफ कर दो, लेकिन यहाँ जाता है:

// Abstract class so you don't have to provide an instance 
@Module 
abstract class ActivityModule { 

    // No need for ActivityScope: You're always binding to the same Activity, so 
    // there's no reason to have Dagger save your Context instance in a Provider. 
    @Binds @ActivityContext 
    abstract fun providesContext(activity: Activity): Context 

    // This doesn't *have* to be in a companion object, but that way 
    // Android can do a static dispatch instead of a virtual method dispatch. 
    // If you don't need that, just skip the constructor arguments and make these 
    // normal methods and you'll be good to go. 
    @Module 
    companion object { 
     @JvmStatic @Provides @ActivityContext 
     fun providesLayoutInflater(activity: Activity): LayoutInflater = 
      activity.layoutInflater 

     @JvmStatic @Provides @ActivityContext 
     fun providesResources(activity: Activity): Resources = activity.resources 
    } 
} 

और अपने मॉड्यूल:

@Module 
internal abstract class AppActivityModule { 

    @Module 
    internal interface WelcomeActivityModule { 
     // The component that @ContributesAndroidInjector generates will bind 
     // your WelcomeActivity, but not your Activity. So just connect the two, 
     // and suddenly you'll have access via injections of Activity. 
     @Binds fun bindWelcomeActivity(activity: WelcomeActivity) : Activity 
    } 

    @ContributesAndroidInjector(
     modules = [ActivityModule::class, WelcomeActivityModule::class]) 
    abstract fun contributeWelcomeActivityInjector(): WelcomeActivity 
} 

ध्यान दें कि हालांकि इस के लिए गतिविधि, सेवा, BroadcastReceiver, और दूसरों के काम करता है, आपने इतनी जल्दी इतना होने के लिए नहीं चाहते हो सकता है इसके बारे में फ्रैगमेंट के लिए। ऐसा इसलिए है क्योंकि dagger.android पैरेंट टुकड़ों के साथ टुकड़े पदानुक्रमों को संभालता है, इसलिए एक बच्चे के घटक के भीतर से आप को आपके अनुप्रयोग, आपकी सक्रियता, आपके माता-पिता की समस्या, और YourChildFragment, और उनके सभी घटकों तक पहुंच हो सकती है। अगर YourChildFragmentComponent में कुछ अयोग्य खंडन पर निर्भर करता है, तो यह संदिग्ध होगा कि क्या यह वास्तव में आपके माता-पिता या आपके चाइल्डफ्रैगमेंट चाहता है। उस ने कहा, यह डिजाइन क्रियाकलापों और कुछ टुकड़ों के लिए समझ में आता है, इसलिए इसका उपयोग करने के लिए यह समझ में आता है (सावधानीपूर्वक)।

+0

सहयोगी वस्तु अभी भी एक वस्तु है, तो आप "आभासी विधि प्रेषण के बजाय स्थैतिक प्रेषण" के बारे में क्या कहते हैं, यह सच नहीं है। @JvmStatic एक स्थैतिक विधि बनाता है, जो साथी ऑब्जेक्ट पर एक इंस्टेंस विधि कहता है। जहां तक ​​मुझे पता है, कोटलिन-केवल कोडबेस में स्थिर प्रदान करने का कोई तरीका नहीं है। या तो आपको जावा में मॉड्यूल या जावा में घटक बनाना है। – arekolek

+0

@arekolek आप सही हैं कि सहयोगी वस्तु को कोटलिन में सिंगलटन के रूप में लागू किया गया है, और कोटलिन में एक उदाहरण कॉल आवश्यक है। (मुझे यह नहीं पता था।) दूसरी तरफ, कोटलिन उस स्थिर 'संकेत' को पारदर्शी रूप से संभालती है, जबकि डैगर को '@ प्रोविड्स' इंस्टेंस विधि दिखाई देगी और मान लीजिए कि प्रत्येक घटक घटक_ को मॉड्यूल का उदाहरण रखने की आवश्यकता है दृश्यों के पीछे कोटलिन क्या करता है। साथ ही, यदि कोटलिन की जेनरेट की गई इंस्टेंस विधि 'अंतिम' है, तो यह स्थिर प्रेषण में _still_ अनुवाद करेगा, भले ही यह एक उदाहरण विधि पर हो। (मुझे बाइटकोड में खोदने की आवश्यकता होगी।) –

+0

हम्म, यह समझ में आता है कि 'स्थैतिक अंतिम' फ़ील्ड में रखी गई ऑब्जेक्ट पर 'अंतिम' विधि को कॉल करने वाली 'स्थिर' विधि को संकलक द्वारा अनुकूलित किया जा सकता है, हालांकि यह पहली बार है जब मैं इसके बारे में सुनता हूं। कोटलिन में डिफ़ॉल्ट रूप से तरीके 'अंतिम' हैं और उन्हें 'ऑब्जेक्ट' में 'ओपन' नहीं बनाया जा सकता है, मैंने बाइटकोड की जांच की है और यह वास्तव में 'अंतिम' है। क्या आप मुझे कुछ दस्तावेज पर इंगित कर सकते हैं जो कहता है कि इस परिदृश्य में कोई वर्चुअल विधि कॉल नहीं होती है? – arekolek

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