【问题标题】:Kotlin Kodein NotFoundException: No binding found for bind<String>() with ?<Fragment>()Kotlin Kodein NotFoundException:没有为 bind<String>() 找到绑定?<Fragment>()
【发布时间】:2019-09-20 16:40:20
【问题描述】:

我有一个非常简单的设置。但是我无法在我正在使用Kodein 的片段中执行任何联网。

片段膨胀并处理所有交互,但网络层依赖项不知何故丢失,因为我每次点击验证此 LoginFragmnet 上的用户名/密码的按钮时都会收到:NotFoundException: No binding found for bind&lt;String&gt;() with ?&lt;Fragment&gt;()

我不明白这个错误,因为我的 Fragment 类在它的 args/constructor 中没有任何 String?甚至依赖String

我的应用程序类:

...
override val kodein = Kodein.lazy {
    import(androidXModule(this@MyApplication))
    bind() from singleton { MyLoginApi(instance(), instance()) }
    bind<LoginDataSource>() with singleton { LoginService(instance()) }
    bind<LoginRepository>() with singleton { LoginRepositoryImpl(instance()) }
}
...

我的 API

interface MyLoginApi {

    @POST("Account/Login")
    @FormUrlEncoded
    fun login(
        @Field("username") username: String,
        @Field("password") password: String,
        @Field("sessionType") sessionType: String
    ): Call<BaseApiResponse<Login>>

    @GET("Account/Logout")
    fun logout(
        @Query("token") token: String
    ): Call<BaseApiResponse<Any>>

    companion object {
        operator fun invoke(
            baseUrl: String,
            cache: Cache
        ): MyLoginApi {

            val okHttpClient = OkHttpClient.Builder()
                .cache(cache)
                .readTimeout(60, TimeUnit.SECONDS)
                .connectTimeout(60, TimeUnit.SECONDS)
                .build()

            return Retrofit.Builder()
                .client(okHttpClient)
                .baseUrl(baseUrl)
                .addConverterFactory(JacksonConverterFactory.create())
                .build()
                .create(MyLoginApi::class.java)
        }
    }
}

LoginService(数据源)

class LoginService(private val api: MyLoginApi) : LoginDataSource {
    private val bus = EventBus.getDefault()

    init {
        bus.register(this)
    }

    override fun requestLogin(username: String, password: String) {
        val call = api.login(username, password, "mobile")
        call.enqueue { result ->
            when (result) {
                is Result.Success -> {

                    result.response.body()?.let {
                        bus.post(LoginResponse(it, username))
                    } ?: bus.post(LoginResponse(IOException("System Error!")))

                }
                is Result.Failure -> {
                    bus.post(LoginResponse(IOException(result.error)))
                }
            }
        }
}

抽象片段类:

abstract class InjectionFragment : Fragment(), KodeinAware {

    final override val kodeinContext = kcontext<Fragment>(this)
    final override val kodein: Kodein by kodein()

    final override val kodeinTrigger: KodeinTrigger?
        get() = if (BuildConfig.DEBUG) KodeinTrigger() else super.kodeinTrigger

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        kodeinTrigger?.trigger()
    }
}

我知道这个场景非常简单,但我正在尝试将其作为测试,然后再集成到项目的其余部分中。 Fragment 显示,但由于某种原因,一旦我尝试执行数据请求,它就会崩溃并显示错误消息:

org.kodein.di.Kodein$NotFoundException: No binding found for bind<String>() with ?<Fragment>().? { ? }

module ⁣androidModule {
bind<String>(tag = "packageResourcePath") with contexted<Context>().provider { String }
bind<String>(tag = "packageCodePath") with contexted<Context>().provider { String }
bind<String>(tag = "packageName") with contexted<Context>().provider { String }
}

更新: 当单步执行我的 Fragment 时,调试器会说 Repository“尚未初始化延迟值。”

【问题讨论】:

  • 您在哪里声明/检索您的字符串packageResourcePathpackageCodePath packageName?我猜这似乎有什么问题,因为您需要一个字符串来进行网络调用。

标签: android android-fragments kotlin dependency-injection kodein


【解决方案1】:

在绑定使用 String 实例的类之前,您应该在 kodein.lazy 初始化中将 String “类”与自身的实例绑定em>

  override val kodein = Kodein.lazy {
  import(androidXModule(this@MyApplication))

  bind() from singleton {String()}     //   --->  Add THIS line

  bind() from singleton { MyLoginApi(instance(), instance()) }
  bind<LoginDataSource>() with singleton { LoginService(instance()) }
  bind<LoginRepository>() with singleton { LoginRepositoryImpl(instance()) }

  }
    ...

您可以这样做,因为在这种情况下,类 String 的构造函数是公共的,但不要将其作为最终解决方案,因为这对于其他数据类型(如 Integer,因为它的构造函数是私有的。

真正的问题可能在于这个绑定

bind() from singleton { MyLoginApi(instance(), instance()) }

MyLoginApi 中的实例是字符串的实例,由于你没有实现 MyLoginApi 接口,Kodein 库直接尝试查找这些实例的定义位置。所以最好创建 MyLoginApiImpl 然后替换:

 bind() from singleton { MyLoginApi(instance(), instance()) }

bind<MyLoginApi>() with singleton { MyLoginApiImpl(instance())}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-26
    • 1970-01-01
    • 1970-01-01
    • 2019-08-16
    • 1970-01-01
    相关资源
    最近更新 更多