嗨,我目前正在探索 KMM 开发,但我陷入了 Context 部分。
我想创建一个类,它将处理安全数据存储。我为 iOS 和 Android 创建了一个 expect class Manager 和两个 actual class Manager。对于 Android 部分,框架和所有其他可用工具都需要 Context。
我想使用这个 Manager 来存储和读取 CommonMain 中的值。但从项目的共享部分来看,没有提供 Context。
我如何实现这一目标?
这是代码:
expect class TokenStore(context: Any) {
fun getToken(): String?
fun saveToken(token: String)
}
import com.liftric.kvault.KVault
actual class TokenStore actual constructor(context: Any) {
private val store = KVault("com.example.keystoreexample")
actual fun getToken(): String? {
val token = store.string("ACCOUNT_TOKEN")
return if (token != null) {
println("✅ The token was found.\nThe value is: $token")
token
} else {
println("❌ There is no token in the Token Store.")
null
}
}
actual fun saveToken(token: String) {
if (token == "") println("⚠️ No token was provided.\nWatch out for this one.")
if (store.existsObject("ACCOUNT_TOKEN")) {
val existingObject = store.string("ACCOUNT_TOKEN")
print("ℹ️ Object is already in the Token Store.\nThe token value is: $existingObject")
if (store.clear()) {
println("✅ All values in Token Store were removed.")
} else {
println("❌ There was an issue removing objects from the Token Store.")
}
} else {
println("ℹ️ Object under this key is not stored in a database yet.")
}
if (store.set("ACCOUNT_TOKEN", token)) {
println("✅ The token was added to the Token Store.")
} else {
println("❌ There was an issue inserting token to the Token Store.")
}
}
}
import android.content.Context
import com.liftric.kvault.KVault
actual class TokenStore actual constructor(private val context: Any) {
private val store = KVault(context as Context)
actual fun getToken(): String? {
val token = store.string("ACCOUNT_TOKEN")
return if (token != null) {
println("✅ The token was found.\nThe value is: $token")
token
} else {
println("❌ There is no token in the Token Store.")
null
}
}
actual fun saveToken(token: String) {
if (token == "") println("⚠️ No token was provided.\nWatch out for this one.")
if (store.existsObject("ACCOUNT_TOKEN")) {
val existingObject = store.string("ACCOUNT_TOKEN")
print("ℹ️ Object is already in the Token Store.\nThe token value is: $existingObject")
if (store.clear()) {
println("✅ All values in Token Store were removed.")
} else {
println("❌ There was an issue removing objects from the Token Store.")
}
} else {
println("ℹ️ Object under this key is not stored in a database yet.")
}
if (store.set("ACCOUNT_TOKEN", token)) {
println("✅ The token was added to the Token Store.")
} else {
println("❌ There was an issue inserting token to the Token Store.")
}
}
}
我想在这里使用它例如:
package com.example.keystoresample
// CommonMain
import TokenStore
class Greeting {
private val platform: Platform = getPlatform()
private val token = TokenStore(context).getToken() // Where can I get it?
fun greet(): String {
return "Hello, ${platform.name}!\nThe token value is:\n$token"
}
}
我想我已经尝试了很多。
这个答案可能为时已晚,但如果其他人面临同样的问题,我想将其留在这里。
您可以使用
androidx.startup
库来获取应用程序上下文的实例。您可以将其存储在变量中并在任何您想要的地方使用它。应用程序上下文存在于整个应用程序生命周期中,因此不存在泄漏上下文的问题。它类似于使用柄在视图模型上注入应用程序上下文。
注意:活动提供的上下文和应用程序上下文之间存在差异。
androidx.startup
对您的 androidMain
源集的依赖。
val androidMain by getting {
dependencies {
implementation("androidx.startup:startup-runtime:1.1.1")
}
}
import android.content.Context
import androidx.startup.Initializer
lateinit var applicationContext: Context
class ApplicationContextInitializer : Initializer<Context> {
override fun create(context: Context): Context = context.also {
applicationContext = it.applicationContext
}
override fun dependencies(): List<Class<out Initializer<*>>> = emptyList()
}
InitializationProvider
<application>
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
android:exported="false"
tools:node="merge">
<!-- Replace com.example with actual package name -->
<meta-data
android:name="com.example.ApplicationContextInitializer"
android:value="androidx.startup" />
</provider>
</application>
仅此而已。