同一类Kotlin中的@Provides和@Binds方法

时间:2018-01-22 17:07:45

标签: kotlin dagger-2

在dagger 2.11之后我们可以使用@Binds注释并在这种情况下将我们的模块标记为抽象,这比具体更有效。

如果我的模块同时具有@Provides和@Binds方法,我有两个选择:

  1. 最简单的方法是将@Provides实例方法标记为静态。

  2. 如果有必要将它们作为实例方法保留,那么就可以 将您的模块拆分为两个并提取所有@Binds方法 进入一个抽象的模块。

  3. 第二个选项在Java和Kotlin中运行正常,但第一个选项在Java中工作正常,但我不知道如何在Kotlin中实现相同的功能。如果我将@Provides方法移动到Companion对象,它会抛出Error:(30, 1) error: @Provides methods can only be present within a @Module or @ProducerModule。 怎么能在Kotlin做到这一点。

    第二个选项:(工作)

    ApplicationModule.kt

    @Module(includes = [ApplicationModule.Declarations::class])
    abstract class ApplicationModule {
        @Module
        internal interface Declarations {
            @Binds
            fun bindContext(application: Application): Context
        }
    
        @Provides
        @Singleton
        fun provideMvpStarterService(): MvpStarterService {
            return MvpStarterServiceFactory.makeStarterService()
        }
    }
    

    第一个选项:(不工作)

    ApplicationModule.kt

    @Module
    abstract class ApplicationModule {
        //expose Application as an injectable context
        @Binds
        internal abstract fun bindContext(application: Application): Context
    
        companion object {
            @JvmStatic
            @Provides
            @Singleton
            fun provideMvpStarterService(): MvpStarterService {
                return MvpStarterServiceFactory.makeStarterService()
            }
        }
    }
    

    为第一个选项生成Java文件:

    @kotlin.Metadata(mv = {1, 1, 9}, bv = {1, 0, 2}, k = 1, d1 = {"\u0000\u001a\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\b\u0002\n\u0002\u0018\u0002\n\u0000\n\u0002\u0018\u0002\n\u0002\b\u0003\b\'\u0018\u0000 \b2\u00020\u0001:\u0001\bB\u0005\u00a2\u0006\u0002\u0010\u0002J\u0015\u0010\u0003\u001a\u00020\u00042\u0006\u0010\u0005\u001a\u00020\u0006H!\u00a2\u0006\u0002\b\u0007\u00a8\u0006\t"}, d2 = {"Lio/mywebsie/di/ApplicationModule;", "", "()V", "bindContext", "Landroid/content/Context;", "application", "Landroid/app/Application;", "bindContext$app_debug", "Companion", "app_debug"})
    @dagger.Module()
    public abstract class ApplicationModule {
        public static final io.mywebsie.di.ApplicationModule.Companion Companion = null;
    
        @org.jetbrains.annotations.NotNull()
        @dagger.Binds()
        public abstract android.content.Context bindContext$app_debug(@org.jetbrains.annotations.NotNull()
        android.app.Application application);
    
        public ApplicationModule() {
            super();
        }
    
        @org.jetbrains.annotations.NotNull()
        @javax.inject.Singleton()
        @dagger.Provides()
        public static final io.mywebsie.data.remote.MvpStarterService provideMvpStarterService() {
            return null;
        }
    
        @kotlin.Metadata(mv = {1, 1, 9}, bv = {1, 0, 2}, k = 1, d1 = {"\u0000\u0012\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\b\u0002\n\u0002\u0018\u0002\n\u0000\b\u0086\u0003\u0018\u00002\u00020\u0001B\u0007\b\u0002\u00a2\u0006\u0002\u0010\u0002J\b\u0010\u0003\u001a\u00020\u0004H\u0007\u00a8\u0006\u0005"}, d2 = {"Lio/mywebsie/di/ApplicationModule$Companion;", "", "()V", "provideMvpStarterService", "Lio/mywebsie/data/remote/MvpStarterService;", "app_debug"})
        public static final class Companion {
    
            @org.jetbrains.annotations.NotNull()
            @javax.inject.Singleton()
            @dagger.Provides()
            public final io.mywebsie.data.remote.MvpStarterService provideMvpStarterService() {
                return null;
            }
    
            private Companion() {
                super();
            }
        }
    }
    

    更新

    感谢 @David Medenjak ,您在评论中提供的link使一切都清晰,我遇到了两种方法来实现第一个选项。

    更新的代码:

    第一个选项:(工作)

    ApplicationModule.kt

    @Module(includes = [ApplicationModule.AModule::class])
    abstract class ApplicationModule {
    
        @Binds
        abstract fun bindContext(application: Application): Context
    
        @Module
        object AModule {
            @JvmStatic
            @Provides
            @Singleton
            fun provideMvpStarterService(): MvpStarterService {
                return MvpStarterServiceFactory.makeStarterService()
            }
        }
    }
    

    @Module
    abstract class ApplicationModule {
        @Binds
        abstract fun bindContext(application: Application): Context
    
        @Module
        companion object {
            @Provides
            @Singleton
            fun provideMvpStarterService(): MvpStarterService {
                return MvpStarterServiceFactory.makeStarterService()
            }
        }
    }
    

    两者都很好但是出于某种原因,第一个选项看起来并不吸引我,所以我更喜欢第二个选项。

1 个答案:

答案 0 :(得分:1)

下面是一个示例代码,用于演示如何在单个SELECT * FROM table WHERE column1 = 'value' AND column2 BETWEEN 1 AND 10000 中使用BindsProvides带注释的方法:

Kotlin class