渐进式编程课
KMP 目录
第 17 课2026.08.02

上一课只定义了 PreferenceStorage 接口。Android 端需要把这个接口映射到真实的平台存储 API,才能让共享 LanguageRepository 保存和读取偏好。

第 17 课:实现 Android 偏好存储

  • 日期:2026-08-02
  • 课程序号:17
  • 知识点:在 androidMain 中用 SharedPreferences 实现共享接口

用途

上一课只定义了 PreferenceStorage 接口。Android 端需要把这个接口映射到真实的平台存储 API,才能让共享 LanguageRepository 保存和读取偏好。

核心概念

  • Android 实现放在 androidMain,可以直接使用 Context 和 SharedPreferences。
  • 使用应用级 Context,避免存储对象持有短生命周期 Activity。
  • getString(key, null) 在键不存在时返回 null,保持共享接口语义。
  • apply() 立即更新内存值,并异步写入磁盘。
  • Android 官方目前更推荐 DataStore;接口隔离让以后更换实现时无需修改共享业务。

示例代码

androidMain/AndroidPreferenceStorage.kt:

kotlin
import android.content.Context

class AndroidPreferenceStorage(
    context: Context,
) : PreferenceStorage {
    private val preferences = context.applicationContext
        .getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE)

    override fun putString(key: String, value: String) {
        preferences.edit()
            .putString(key, value)
            .apply()
    }

    override fun getString(key: String): String? {
        return preferences.getString(key, null)
    }

    override fun remove(key: String) {
        preferences.edit()
            .remove(key)
            .apply()
    }

    companion object {
        private const val FILE_NAME = "app_preferences"
    }
}

在 Android 组合根中注入真实实现:

kotlin
val storage: PreferenceStorage =
    AndroidPreferenceStorage(applicationContext)

val languageRepository = LanguageRepository(storage)

共享 LanguageRepository 不需要增加任何 Android 判断。

5 分钟练习

写出保存并读取 "en-US" 的调用代码,然后说明数据实际由哪一层写入 SharedPreferences。

参考答案

kotlin
val storage = AndroidPreferenceStorage(applicationContext)
val repository = LanguageRepository(storage)

repository.saveLanguage("en-US")
val language = repository.loadLanguage()

println(language) // en-US

LanguageRepository 决定业务键和值,AndroidPreferenceStorage 才是实际调用 SharedPreferences 的平台实现层。

与上一课的联系

上一课定义了共享存储协议和内存 Fake;本课没有改变共享接口,只在 androidMain 接入 Android 平台 API,证明同一个 Repository 可以替换底层实现。

参考资料