问题描述
在匕首2.11之后,我们可以使用@Binds批注并在这种情况下将模块标记为抽象,这比具体方法更有效.
After dagger 2.11 we can use a @Binds annotation and mark our Module as abstract in this case which is more efficient than a concrete.
如果我的模块同时具有@Provides和@Binds方法,则我有两个选择:
If my Module has both @Provides and @Binds methods, I have two options :
-
最简单的方法是将@Provides实例方法标记为静态.
Simplest would be to mark your @Provides instance methods as static.
如果有必要将其保留为实例方法,则可以将您的模块一分为二并提取所有@Binds方法进入一个抽象模块.
If it is necessary to keep them as instance methods, then you cansplit your module into two and extract out all the @Binds methodsinto an abstract Module.
第二个选项在Java和Kotlin中运行良好,但是第一个选项在Java中运行良好,但是我不知道如何在Kotlin中实现相同的功能.如果我将@Provides方法移至Companion对象,则会抛出Error:(30, 1) error: @Provides methods can only be present within a @Module or @ProducerModule
.如何在Kotlin中做到这一点.
The second option works fine in Java and Kotlin but the first option works fine in Java but I don't know how to implement the same in Kotlin. If I move @Provides method to Companion object it throw Error:(30, 1) error: @Provides methods can only be present within a @Module or @ProducerModule
.How can do this in Kotlin.
第二个选项:(正在运行)
ApplicationModule.kt
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
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文件:
Generated Java file for first option:
@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 链接可以通过两种方式来实现第一种选择.
Thanks to @David Medenjak the link you provided in comment made everything clear I came across two ways to achieve the first option.
更新的代码:
第一个选项:(正在工作)
ApplicationModule.kt
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()
}
}
}
两种方法都很好,但是由于某种原因,第一种选择对我来说似乎并不吸引人,所以我更喜欢第二种选择.
Both works just fine but for some reason the first option does not look appealing to me so I prefer the second option.
推荐答案
下面是一个示例代码,用于演示如何在单个Kotlin class
中使用Binds
和Provides
批注的方法:
Here's an example code to demonstrate how to use Binds
and Provides
annotated methods in a single Kotlin class
:
@Module
abstract class MessagesPresentationModule {
@Module
companion object {
const val MESSAGES = 0x00
@JvmStatic
@Provides
fun provideRecyclerAdapter(
itemComparator: DisplayItemComperator,
factoryMap: Map<Int, ViewHolderFactory>,
binderMap: Map<Int, ViewHolderBinder>,
androidPreconditions: AndroidPreconditions
): RecyclerViewAdapter {
return RecyclerViewAdapter(
itemComperator = itemComparator,
viewHolderFactoryMap = factoryMap,
viewBinderFactoryMap = binderMap,
androidPreconditions = androidPreconditions
)
}
}
@Binds
@IntoMap
@IntKey(MESSAGES)
internal abstract fun provideMessagesViewModelFactory(factory: MessagesViewHolder.MessageViewHolderFactory): ViewHolderFactory
@Binds
@IntoMap
@IntKey(MESSAGES)
internal abstract fun provideMessagesViewHolderBinder(binder: MessagesViewHolder.MessagesViewHolderBinder): ViewHolderBinder
}
这篇关于同一类Kotlin中的@Provides和@Binds方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!