KMM开发:如何在CommonMain中获取Context使用TokenStore?
Kotlin Multiplatform Mobile 在CommonMain中处理Context问题
针对你在KMM开发中遇到的CommonMain无法直接获取Context、无法使用TokenStore的问题,以下是几种可行的解决方案:
方案一:依赖注入传递TokenStore实例
Common层不负责创建TokenStore,而是由平台层完成初始化(传入所需的Context),再将实例传递给Common层的业务类。
步骤1:修改CommonMain的Greeting类
让Greeting接收TokenStore作为构造参数,避免在Common层处理Context:
// CommonMain class Greeting(private val tokenStore: TokenStore) { private val platform: Platform = getPlatform() private val token = tokenStore.getToken() fun greet(): String { return "Hello, ${platform.name}!\nThe token value is:\n$token" } }
步骤2:优化TokenStore的expect定义
为了让iOS端无需传递无用参数,调整expect的构造函数:
// CommonMain expect class TokenStore { constructor(context: android.content.Context) // Android专用构造 constructor() // iOS专用构造 fun getToken(): String? fun saveToken(token: String) }
步骤3:平台层实现并传递实例
- Android端(AndroidMain):
// AndroidMain import android.content.Context import com.liftric.kvault.KVault actual class TokenStore actual constructor(private val context: Context) { private val store = KVault(context) // 原有getToken、saveToken方法不变 } // 在Activity/Application中创建实例并传入Greeting val context = applicationContext val tokenStore = TokenStore(context) val greeting = Greeting(tokenStore)
- iOS端(iOSMain):
// iOSMain import com.liftric.kvault.KVault actual class TokenStore actual constructor() { private val store = KVault("com.example.keystoreexample") // 原有getToken、saveToken方法不变 } // 创建实例并传入Greeting val tokenStore = TokenStore() val greeting = Greeting(tokenStore)
方案二:通过expect/actual提供全局Context
定义全局的Context获取入口,由平台层实现Context的提供逻辑:
步骤1:CommonMain定义expect
// CommonMain expect object PlatformContext { val appContext: Any? }
步骤2:平台层实现actual
- Android端(AndroidMain):
// AndroidMain import android.content.Context import android.app.Application actual object PlatformContext { lateinit var internalContext: Context actual val appContext: Any? get() = if (::internalContext.isInitialized) internalContext else null } // 在Application类中初始化 class MyApp : Application() { override fun onCreate() { super.onCreate() PlatformContext.internalContext = this } }
- iOS端(iOSMain):
// iOSMain actual object PlatformContext { actual val appContext: Any? = null // iOS无需Context,返回null即可 }
步骤3:CommonMain中使用
// CommonMain class Greeting { private val platform: Platform = getPlatform() private val tokenStore = TokenStore(PlatformContext.appContext!!) private val token = tokenStore.getToken() fun greet(): String { return "Hello, ${platform.name}!\nThe token value is:\n$token" } }
注意:Android端必须确保
PlatformContext在Application中完成初始化,否则会触发空指针异常。
方案三:依赖倒置,用接口+工厂方法解耦
Common层只定义TokenStore的抽象接口,平台层负责实现和提供实例:
步骤1:CommonMain定义接口和工厂方法
// CommonMain interface TokenStore { fun getToken(): String? fun saveToken(token: String) } expect fun provideTokenStore(): TokenStore
步骤2:平台层实现接口和工厂方法
- Android端(AndroidMain):
// AndroidMain import android.content.Context import com.liftric.kvault.KVault class AndroidTokenStore(private val context: Context) : TokenStore { private val store = KVault(context) // 实现getToken、saveToken方法(和原有逻辑一致) } actual fun provideTokenStore(): TokenStore { return AndroidTokenStore(PlatformContext.appContext) }
- iOS端(iOSMain):
// iOSMain import com.liftric.kvault.KVault class IosTokenStore : TokenStore { private val store = KVault("com.example.keystoreexample") // 实现getToken、saveToken方法(和原有逻辑一致) } actual fun provideTokenStore(): TokenStore { return IosTokenStore() }
步骤3:CommonMain中使用
// CommonMain class Greeting { private val platform: Platform = getPlatform() private val tokenStore = provideTokenStore() private val token = tokenStore.getToken() fun greet(): String { return "Hello, ${platform.name}!\nThe token value is:\n$token" } }
方案推荐
优先选择方案一或方案三:依赖注入和依赖倒置的方式更灵活,避免全局变量带来的初始化顺序问题,也更便于单元测试。
内容的提问来源于stack exchange,提问作者Jan Janovec
相关产品推荐
相关产品推荐

