我有使用 KMM 构建的 MVVM 应用程序。ViewModel 包含几个用例。每个用例调用 Repository 的方法,Repository 调用 NetworkService 来执行 API 调用。用例、Repository 和 NetworkService 在共享模块中。我需要将所有 cookie 存储在从服务器接收到的共享首选项中。为此,我创建了自己的 cookie 存储并以这种方式安装它:
private val httpClient = HttpClient {
install(HttpCookies) {
storage = CookiesStorage(di)
}
}
这是cookies存储的代码:
class CookiesStorage(val di: DI) : CookiesStorage {
private val cookiesStorageImpl = CookiesStorageImpl(di)
override suspend fun addCookie(requestUrl: Url, cookie: Cookie) {
cookiesStorageImpl.addCookie(requestUrl, cookie)
}
override fun close() {
}
override suspend fun get(requestUrl: Url) = cookiesStorageImpl.getCookies()
}
expect class CookiesStorageImpl(di: DI) {
val di: DI
fun addCookie(requestUrl: Url, cookie: Cookie)
fun getCookies(): MutableList<Cookie>
}
由于在 iOS 和 Android 中存储键值数据的工作不同,我添加了 expect class CookiesStorageImpl
。此类的 Android 实现现在如下:
actual class CookiesStorageImpl actual constructor(actual val di: DI) {
private val cookieMap = mutableMapOf<String, String>()
private val context: Context by di.instance()
actual fun addCookie(requestUrl: Url, cookie: Cookie) {
println("Set cookie name=${cookie.name}, value=${cookie.value}")
cookieMap[cookie.name] = cookie.value
context.getSharedPreferences("kmm_preferences", Context.MODE_PRIVATE)
}
actual fun getCookies() = mutableListOf<Cookie>().apply {
cookieMap.forEach {
this.add(Cookie(it.key, it.value))
}
}
}
如您所见,我在这里使用 di 初始化上下文。
这是android应用程序中的di图:
val appModule = DI.Module("app module") {
import(viewModelModule)
bind<Context>() with multiton { app: App ->
app.applicationContext
}
}
val viewModelModule = DI.Module("view model module") {
import(useCaseModule)
bind<ViewModelProvider.Factory>() with singleton {
ViewModelFactory(instance())
}
bind<LoginViewModel>() with provider {
LoginViewModel(instance())
}
}
这是共享模块的DI:
val useCaseModule = DI.Module("use case module") {
bind<LoginUseCase>() with singleton {
LoginUseCase(di)
}
}
因此,如您所见,我只是di
从用例传递到CookiesStorageImpl
. 但是当我运行应用程序时,访问上下文时出现以下错误:
org.kodein.di.DI$NotFoundException: No binding found for bind<Context> { ? { ? } }
因此,据我了解,问题在于 UseCase 对上下文一无所知,但我不明白如何将绑定传递给用例模块。提前感谢您的帮助!
UPD
这是我在 Application 类中添加图形的方式:
class App : Application(), DIAware {
override val di by DI.lazy {
import(appModule)
}
}