Mr.Liu
文章3
标签4
分类3

文章归档

Kotlin Multiplatform (KMP) 项目的探索

Kotlin Multiplatform (KMP) 项目的探索

之前一直有在用Jetpack Compose开发一个PiPixiv的Android应用,最近关注到KMP已经可以投入生产环境了,觉得是一个很不错的方向,所以就想尝试一下把现有的Compose代码迁移到KMP。这篇文章主要是记录我在学习KMP过程中的一些心得和体会。

什么是Kotlin Multiplatform (KMP)

先简单介绍一下,Kotlin Multiplatform (KMP) 是使用Kotlin语言开发跨平台应用程序的框架。KMP允许开发人员在多个平台上共享代码,包括Android、iOS、Web、桌面和服务器端。其目标是提供一种简单而强大的方法,让开发人员能够在不同平台上共享代码,同时通过Kotlin/Native保持对每个平台的原生特性的访问。

KMP的架构

KMP在架构上主要分为逻辑层和UI层:

KMP架构设计比较优秀的地方在于每个层都是可插拨的,这样可以根据不同的需求和平台选择不同的实现。

通常有以下几种类型:

  • 共享部分逻辑代码

    共享应用的独立关键部分以提高应用稳定性。重用已有的 Kotlin 代码使应用程序保持同步。

  • 共享整个业务逻辑

    共享与业务相关的内容,包括数据模型、网络请求、数据库访问等。同时保持 UI 原生以满足最严格的要求。

  • 共享整个UI和业务逻辑

    使用 Compose Multiplatform 共享UI层,逻辑层使用Kotlin Multiplatform共享。同时Compose Multiplatform还可以和SwiftUI等UI框架混合使用。
    在混用UI的情况下,通常采用的做法是使用Compose构建一些通用组件,然后在各自原生平台上使用

原Android项目的结构

整个应用遵循Google官方推荐的分层架构,整体上采用MVI架构,使用Koin来进行依赖注入,网络层使用Retrofit+OkHttp,图片加载使用Coil,本地存储暂时只用到DataStore

主要分为以下几个模块:

  • api:Retrofit网络请求接口
  • app:Android应用模块
  • common:通用模块,包含一些通用的工具类和数据模型以及BaseActivity, BaseViewModel等
  • data:数据模块,网络请求和本地存储数据结构
  • domain:业务逻辑模块,拆分一些通用的UseCase
  • feature:功能模块,按功能模块划分,每个模块包含Compose页面、ViewModel、拆分的Compose Component等
  • repository:数据仓库模块,提供数据获取的方法,每个repository可以整合多个本地/远程datasource,对ViewModel提供统一的数据获取接口
  • datasource:数据源模块,提供数据获取的实现,包括网络请求和本地存储
  • network:网络模块,提供网络请求的实现,包括Retrofit和OkHttp的配置,同时自定义Converter,将网络请求的数据转换为Kotlin
    Flow
  • util:工具类模块,提供一些通用的工具类

开始迁移

由于原项目已经使用了Compose,所以迁移的工作主要是将原有的业务逻辑代码迁移到KMP中。
原有的UI层代码可以基本保持不变,只需将部分Android特有的代码在commonMain模块中使用expect/actual进行替换即可,同时使用Kotlin/Native实现在iOS上对应功能。

在KMP项目中,精简了部分模块,去除api、common-middleware、common-ui、domain等模块

我在实际迁移的过程中,代码改动比较小,原因是原项目中采用的Koin、OkHttp、Coil和Datastore这些都是支持KMP的,只需要将原有的代码做微小调整即可。
主要改动的部分在于:

  • datasource: 远程部分中Retrofit不适用于KMP,使用Ktor替代Retrofit,在安卓端使用OkHttp client,iOS端使用Darwin client
  • ViewModel: 整个项目最关键的迁移就在ViewModel中,目前KMP还没有提供ViewModel的支持,所以需要自己实现一个ViewModel,这里我使用了开源库Decompose+MVIKotlin来实现MVI架构的类ViewModel部分。

Decompose为KMM提供了一套完整的解决方案,包括路由、状态管理、生命周期管理等,而MVIKotlin提供了一套MVI架构的实现,可以很方便的和Decompose结合使用。

资源文件的迁移

在KMP中,资源文件的处理比较麻烦,因为KMP目前只支持单模块的资源文件在内部使用,具体可以参考官方文档,如果涉及到多模块的资源共享,可以参考moko-resources这个项目

iOS端的构建问题

目前官方的resources插件实测还不能对iOS端的资源文件进行增量处理,所以在iOS端的构建中需要手动将资源文件拷贝到对应的目录下
使用Android Studio开发,需要将所有资源文件放到
build/ios/(Debug|Release)-(iphoneos|iphonesimulator)/iOS应用名称.app/common-resources
目录下,才能在iOS端正常加载资源文件

总结

KMP的确是一个不错的方向,可以让开发者在多个平台上共享代码,提高开发效率,但是目前KMP还处于不断发展的阶段,还有很多不完善的地方,比如资源文件的处理、ViewModel的支持等,但是相信随着JetBrains的发力,KMP会变得越来越完善,也希望KMP能够越来越好,让我们的开发变得更加高效。

本文只是简单介绍了KMP的迁移内容,在后面的文章中,我会在实际代码层面继续分享我在KMP项目中的一些心得和体会,欢迎大家关注我的GitHub

本文作者:Mr.Liu
本文链接:https://lzh666.top/2024/03/26/Kotlin-Multiplatform-KMP-%E9%A1%B9%E7%9B%AE%E7%9A%84%E6%8E%A2%E7%B4%A2/
版权声明:本文采用 CC BY-NC-SA 3.0 CN 协议进行许可