【问题标题】:How to add correctly two modules in koin?如何在 koin 中正确添加两个模块?
【发布时间】:2020-07-03 05:59:35
【问题描述】:

我正在开发一个新闻应用程序,我想在应用程序类中添加两个模块,但出现以下异常。

java.lang.RuntimeException: Unable to create application yodgorbek.komilov.musobaqayangiliklari.di.application.SportNewsApplication: org.koin.core.error.DefinitionOverrideException: Already existing definition or try to override an existing one: [type:Single,primary_type:'yodgorbek.komilov.musobaqayangiliklari.internet.SportNewsInterface']
 at android.app.ActivityThread.handleBindApplication(ActivityThread.java:5971)
 at android.app.ActivityThread.access$1300(ActivityThread.java:206)
 at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1700)
 at android.os.Handler.dispatchMessage(Handler.java:106)
 at android.os.Looper.loop(Looper.java:201)
 at android.app.ActivityThread.main(ActivityThread.java:6820)
 at java.lang.reflect.Method.invoke(Native Method)
 at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:922)
Caused by: org.koin.core.error.DefinitionOverrideException: Already existing definition or try to override an existing one: [type:Single,primary_type:'yodgorbek.komilov.musobaqayangiliklari.internet.SportNewsInterface']
 at org.koin.core.registry.BeanRegistry.addDefinition(BeanRegistry.kt:144)
 at org.koin.core.registry.BeanRegistry.saveDefinition(BeanRegistry.kt:101)
 at org.koin.core.registry.BeanRegistry.saveDefinitions(BeanRegistry.kt:71)
 at org.koin.core.registry.BeanRegistry.loadModules(BeanRegistry.kt:49)
 at org.koin.core.KoinApplication.loadModulesAndScopes(KoinApplication.kt:66)
 at org.koin.core.KoinApplication.modules(KoinApplication.kt:60)
 at yodgorbek.komilov.musobaqayangiliklari.di.application.SportNewsApplication$onCreate$1.invoke(SportNewsApplication.kt:19)
 at yodgorbek.komilov.musobaqayangiliklari.di.application.SportNewsApplication$onCreate$1.invoke(SportNewsApplication.kt:11)
 at org.koin.core.context.GlobalContextKt.startKoin(GlobalContext.kt:72)
 at yodgorbek.komilov.musobaqayangiliklari.di.application.SportNewsApplication.onCreate(SportNewsApplication.kt:16)
 at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1155)
 at android.app.ActivityThread.handleBindApplication(ActivityThread.java:5966)
 ... 8 more

在 SportNewsApplication.kt 类下

class SportNewsApplication : Application() {

    override fun onCreate() {
        super.onCreate()
        // Adding Koin modules to our application
        startKoin {

          //  androidContext(this@SportNewsApplication)
            modules(
            listOf(appModules, bbcModules))

        }
    }
}

在 appModules.kt 下

const val BASE_URL = "https://newsapi.org/"

val appModules = module {
    // The Retrofit service using our custom HTTP client instance as a singleton
    single {
        createWebService<SportNewsInterface>(
            okHttpClient = createHttpClient(),
            factory = RxJava2CallAdapterFactory.create(),
            baseUrl = BASE_URL
        )
    }
    // Tells Koin how to create an instance of CatRepository
    factory<NewsRepository> { (NewsRepositoryImpl(sportsNewsApi = get())) }
    // Specific viewModel pattern to tell Koin how to build MainViewModel
    viewModel { MainViewModel(newsRepository = get()) }
}

/* Returns a custom OkHttpClient instance with interceptor. Used for building Retrofit service */
fun createHttpClient(): OkHttpClient {
    val client = OkHttpClient.Builder()
    client.readTimeout(5 * 60, TimeUnit.SECONDS)
    return client.addInterceptor {
        val original = it.request()
        val requestBuilder = original.newBuilder()
        requestBuilder.header("Content-Type", "application/json")
        val request = requestBuilder.method(original.method, original.body).build()
        return@addInterceptor it.proceed(request)
    }.build()
}

/* function to build our Retrofit service */
inline fun <reified T> createWebService(
    okHttpClient: OkHttpClient,
    factory: CallAdapter.Factory, baseUrl: String
): T {
    val retrofit = Retrofit.Builder()
        .baseUrl(baseUrl)
        .addConverterFactory(GsonConverterFactory.create(GsonBuilder().setLenient().create()))
        .addCallAdapterFactory(CoroutineCallAdapterFactory())
        .addCallAdapterFactory(factory)
        .client(okHttpClient)
        .build()
    return retrofit.create(T::class.java)
}

在 bbcModules.kt 下方

const val base_url = "https://newsapi.org/"

val bbcModules = module {
    // The Retrofit service using our custom HTTP client instance as a singleton
    single {
        createBBCWebService<SportNewsInterface>(
            okHttpClient = createBBCHttpClient(),
            factory = RxJava2CallAdapterFactory.create(),
            baseUrl = base_url
        )
    }
    // Tells Koin how to create an instance of CatRepository
    factory<BBCRepository> { (BBCRepositoryImpl(bbcsportNewsApi = get())) }
    // Specific viewModel pattern to tell Koin how to build MainViewModel
    viewModel { BBCSportViewModel(bbcRepository = get()) }
}

/* Returns a custom OkHttpClient instance with interceptor. Used for building Retrofit service */
fun createBBCHttpClient(): OkHttpClient {
    val client = OkHttpClient.Builder()
    client.readTimeout(5 * 60, TimeUnit.SECONDS)
    return client.addInterceptor {
        val original = it.request()
        val requestBuilder = original.newBuilder()
        requestBuilder.header("Content-Type", "application/json")
        val request = requestBuilder.method(original.method, original.body).build()
        return@addInterceptor it.proceed(request)
    }.build()
}

/* function to build our Retrofit service */
inline fun <reified T> createBBCWebService(
    okHttpClient: OkHttpClient,
    factory: CallAdapter.Factory, baseUrl: String
): T {
    val retrofit = Retrofit.Builder()
        .baseUrl(baseUrl)
        .addConverterFactory(GsonConverterFactory.create(GsonBuilder().setLenient().create()))
        .addCallAdapterFactory(CoroutineCallAdapterFactory())
        .addCallAdapterFactory(factory)
        .client(okHttpClient)
        .build()
    return retrofit.create(T::class.java)
}

我尝试过的

1.clean 重建和无效缓存重启和其他 StackOverflow 答案 它没有解决我的问题。

  1. 我也关注了以下链接https://github.com/InsertKoinIO/koin/issues/420

我想知道我必须做什么才能解决异常。

【问题讨论】:

    标签: android kotlin mvvm dependency-injection koin


    【解决方案1】:

    看起来您尝试在不同的模块中创建两个 OkHttpClient 实例。您可以使用模块的覆盖参数来覆盖另一个实例 (module(override = true)) 但在这种情况下,这是不正确的。您必须有两个不同的实例 OkHttpClient。为此,您可以使用命名实例

    single<OkHttpClient>(named("WebService")) {
            createWebService<SportNewsInterface>(
                okHttpClient = createHttpClient(),
                factory = RxJava2CallAdapterFactory.create(),
                baseUrl = BASE_URL
            )
        }
    

    single<OkHttpClient>(named("BBCWebService")) {
            createBBCWebService<SportNewsInterface>(
                okHttpClient = createBBCHttpClient(),
                factory = RxJava2CallAdapterFactory.create(),
                baseUrl = base_url
            )
        }
    

    如果需要注入特定客户端需要使用

    SomeClassNeedDependency(get(named("WebService")))
    

    More information

    【讨论】:

      【解决方案2】:

      尝试使用named。这是doc

      在 appModules.kt 下

      single(named("appModules")) {
              createBBCWebService<SportNewsInterface>(
                  okHttpClient = createBBCHttpClient(),
                  factory = RxJava2CallAdapterFactory.create(),
                  baseUrl = base_url
              )
          }
      
      factory<NewsRepository> { (NewsRepositoryImpl(sportsNewsApi = get(named("appModules")))) }
      
      

      在 bbcModules.kt 下方

      single(named("bbcModules")) {
              createBBCWebService<SportNewsInterface>(
                  okHttpClient = createBBCHttpClient(),
                  factory = RxJava2CallAdapterFactory.create(),
                  baseUrl = base_url
              )
          }
      
          factory<BBCRepository> { (BBCRepositoryImpl(bbcsportNewsApi = get(named("bbcModules")))) }
      
      

      【讨论】:

        猜你喜欢
        • 2021-10-16
        • 2020-05-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-10-15
        • 1970-01-01
        相关资源
        最近更新 更多