代码之家  ›  专栏  ›  技术社区  ›  Benjamin Kevin Rameshwaran

使用匕首2提供函数依赖

  •  4
  • Benjamin Kevin Rameshwaran  · 技术社区  · 7 年前

    我想用匕首2提供一个依赖函数:

    @Module
    class DatabaseModule {
    
        @Provides
        @Singleton
        fun provideDatabase(application: Application, betaFilter: (BetaFilterable) -> Boolean): Database {
            return Database(application, BuildConfig.VERSION_CODE, betaFilter)
        }
    
        @Provides
        @Suppress("ConstantConditionIf")
        fun provideBetaFiler(): (BetaFilterable) -> Boolean {
            return if (BuildConfig.FLAVOR_audience == "regular") {
                { it.betaOnly.not() }
            } else {
                { true }
            }
        }
    
    }
    

    不幸的是,它似乎不起作用:

    [dagger.android.AndroidInjector.inject(T)] kotlin.jvm.functions.Function1<? 
    super com.app.data.BetaFilterable,java.lang.Boolean> 
    cannot be provided without an @Provides-annotated method.
    

    我错过了什么?

    3 回复  |  直到 7 年前
        1
  •  8
  •   Julian A.    7 年前

    是的,这可以在科特林完成。

    您需要在注入站点添加@jvmsuppresswildcards,以确保 签名匹配。 ( source )

    我写了以下内容来验证:

    import dagger.Component
    import dagger.Module
    import dagger.Provides
    import javax.inject.Singleton
    
    class G constructor(val function: Function1<Int, Boolean>)
    
    @Singleton
    @Module
    class ModuleB {
        @Provides
        fun intToBoolean(): (Int) -> Boolean {
            return { it == 2 }
        }
        @JvmSuppressWildcards
        @Provides fun g(intToBoolean: (Int) -> Boolean): G {
            return G(intToBoolean)
        }
    }
    
    @Singleton
    @Component(modules = [ModuleB::class])
    interface ComponentB {
        fun g(): G
    }
    
    val componentB = DaggerComponentB.create()
    val g = componentB.g()
    println(g.function(2)) // true
    println(g.function(3)) // false
    
        2
  •  3
  •   Kiskae    7 年前

    它不起作用,因为为了允许调用具有超类型的函数来代替lambda( (Any) -> Boolean 也可用于 (BetaFilterable) -> Boolean )函数作为参数生成字节码以允许此操作。

    以下代码:

    object Thing
    
    fun provide(): (Thing) -> Boolean {
        TODO()
    }
    
    fun requires(func: (Thing) -> Boolean) {
        TODO()
    }
    

    产生以下签名:

    签名 ()Lkotlin/jvm/functions/Function1<LThing;Ljava/lang/Boolean;> (二)

    宣言: kotlin.jvm.functions.Function1<Thing, java.lang.Boolean> provide()

    签名 (Lkotlin/jvm/functions/Function1<-LThing;Ljava/lang/Boolean;>;)V

    宣言: void requires(kotlin.jvm.functions.Function1<? super Thing, java.lang.Boolean>)

    两者之间的细微差别 -LThing ( ? super Thing )以及 LThing ( Thing )使类型与匕首不兼容。

    我不相信这是可行的,你需要定义一个独立的接口 ? super / ? extends 属性为 Function1 有。

        3
  •  2
  •   Benjamin Kevin Rameshwaran    7 年前

    正如Kiskae的回答所指出的,使用Kotlin是不可能做到这一点的。您可以使用Java来实现:

    @Module
    public class DatabaseModuleJava {
    
        @Provides
        @Singleton
        public Database provideDatabase(Application application, Function1<BetaFilterable, Boolean> betaFilter) {
            return new Database(application, BuildConfig.VERSION_CODE, betaFilter);
        }
    
        @Provides
        @Singleton
        @SuppressWarnings("ConstantConditions")
        public Function1<BetaFilterable, Boolean> provideBetaFiler() {
            if (BuildConfig.FLAVOR_audience.equals("regular")) {
                return betaFilterable -> !betaFilterable.getBetaOnly();
            } else {
                return betaFilterable -> true;
            }
        }
    
    }
    
    推荐文章