Kotlin Multiplatform项目结构、图片显示及SharedPreferences实现问题
Kotlin Multiplatform项目问题解答
1. 项目结构合理性确认
你的项目结构整体符合JetBrains官方KMM项目规范,不过有几个可优化的细节:
jvmAndAndroidMain源集的使用逻辑没问题,但要确保common模块的build.gradle.kts中正确配置该源集的依赖,避免重复引入依赖包。- 安卓端
MainActivity仅负责启动Compose内容的设计是合理的,符合KMM跨平台UI的分工原则。 - 注意
common/src/commonMain/resources作为资源根目录,安卓端需要在common模块的Gradle配置中添加资源复制逻辑,否则安卓系统无法识别这些资源(这也是你第二个问题的核心诱因)。
2. 跨平台图片加载问题
桌面端可直接通过路径加载commonMain内的图片,但安卓端资源系统基于编译生成的R类ID运行,无法直接识别路径,且commonMain的资源不会自动生成安卓的R文件,因此报错。推荐两种解决方案:
方案一:用expect/actual封装图片加载
在commonMain的Platform.kt中定义预期函数:
expect fun getImagePainter(imgName: String): Painter
在androidMain的Platform.kt中实现安卓端逻辑:
actual fun getImagePainter(imgName: String): Painter { val resId = when(imgName) { "a" -> R.drawable.a "b" -> R.drawable.b "c" -> R.drawable.c else -> throw IllegalArgumentException("Unknown image: $imgName") } return painterResource(resId) }
在desktopMain的Platform.kt中实现桌面端逻辑:
actual fun getImagePainter(imgName: String): Painter { return painterResource("drawable/${imgName}.png") }
之后在Application.kt中调用getImagePainter(imgName)即可实现跨平台图片加载。
方案二:同步common资源到安卓端
在common模块的build.gradle.kts中添加Gradle任务,将commonMain/resources/drawable下的图片自动复制到安卓模块的src/main/res/drawable目录,这样安卓端就能通过R.drawable访问,同时保持资源的统一性。
3. 安卓端SharedPreferences获取Context避免循环依赖
通过MainActivity伴生对象获取Context会导致循环依赖(安卓模块依赖common模块,而common又引用安卓模块的MainActivity),正确做法是使用Application级别的Context:
- 在安卓模块中创建自定义Application类:
class MyApp : Application() { companion object { lateinit var context: Context private set } override fun onCreate() { super.onCreate() context = applicationContext } }
- 在
AndroidManifest.xml中注册该Application:
<application android:name=".MyApp" ...> ... </application>
- 在
common/src/androidMain/Platform.kt中直接使用MyApp.context获取上下文:
val sharedPreferences = MyApp.context.getSharedPreferences("app_data", Context.MODE_PRIVATE)
这种方式不会产生循环依赖,因为安卓模块依赖common模块,common的androidMain源集可正常访问安卓模块的类。
内容的提问来源于stack exchange,提问作者Aditya Verma
相关产品推荐
相关产品推荐

