截止上周(本文写于2023.02.07),JetBrains推出Compose跨平台已经发布了1.3.0版本,可以说是很稳定了。很明显这也是跨平台UI的一个很好的方案。
如果你还不了解Compose Multiplatform是什么, 也可以直接参考官网的JetBrains 网站的『长懒看』说明,一句话就是:
Fast reactive Desktop and Web UI framework for Kotlin,JetBrain公司基于Google的 先进工具套件compose,为开发者打造了一套快速响应的桌面端的web端 UI框架,可以完全使用kotlin开发。
因为和jetpack Compose绑定到一起了,相信大部分android 开发者一下子就明白:我们现在可以直接仅用kotlin就打造全平台跨平台的app了。
老哥,为啥不用flutter呢?有区别么?
其实二者还是有相当大的不同的。Kotlin跨平台技术(后文称KMP)和flutter相比,最主要的优势就是不用再学一个新的语言Dart了,直接用koltin就可以搞定,降低了学习成本。除此之外,我还发现了一个有趣的不同之处——他们处理跨平台架构的方案完全不同。
使用Flutter的时候,你需要先写好基础的 业务逻辑、UI逻辑,都只写一次,之后这些基础逻辑就能在不同的平台上直接运行了。你也可以继续写一些对不同平台的适配代码,来优化在特定平台运行的兼容性效果。但,无论你怎么写,真正运行到移动设备、桌面app或者是网页端的时候,你的程序还是由Flutter引擎(由Skia图像处理库构建的引擎)渲染出来而不是直接在操作系统层级渲染的。这就导致它的可移植性很好,但是UI效果并不好,和原生效果还是有些差距。
然而,使用KMP的话,你的业务逻辑还是只写一次,但是后面的UI界面,你需要使用kotlin对目标平台分别编写。虽然大多都可以使用kt语言,但是写法还是有区别的。比如,写android就需要用jetpack Compose框架,iOS就用swift写,桌面端就用compose Multiplatform写,等等。因此,你的app最终会有一个更接近原生的UI效果 —— 只是可移植性就差一些。
最重要的是,这两者提供了不同的方法,怎么用还是得看你的业务场景。
说实话,整体来说还是KMP听起来更好,信我!
理论到此为止!说了这么久,让你有一个初步的感受。但让我们暂时把理论放在一边,关注『怎么用』
新建一个Demo APP
还是得实操一下,要决定开发点什么东西,才能展示所有要了解的实战内容。 Flutter 也有“Hello World” 项目,从这找点儿灵感,制作一个计数器应用程序,允许用户递增和递减一个数值,并记录最新注册的操作是什么。
想要实现上图这个app,我们得决定好使用什么样的架构
选取架构
我们将使用 干净架构(MVVM),这是构建 GUI 应用程序(尤其是在 Android 上)的常用解决方案。 写Android的肯定是对这个架构老生常谈啦。如果你不太了解这个架构,而且感兴趣,也可以先关掉页面去研究一下~比如这个链接-Android干净架构教程
好了,到这就可以开始开工了!我们会用如下几个砖块,构建堆砌我们的app:
Domain:就是Model层,正常应该包括app的全部model,但是这个比较简单,只需要一个data class
数据类。 Data:我们的抽象数据源,就是保存这个计数器app的数据的。 Use Cases:所有的用例类,就是:递增计数器、递减计数器并获取其值的方法。 Presentation:界面对应的viewModel,梳理页面操作逻辑。 Framework:数据源实现以及每个平台的用户界面。
注意:上述所有『砖块』,除了只有Framework里面的UI部分,都是可以跨平台复用的。
开始写代码吧
好了,现在可以开始写代码了,我们用Intellij Idea作为示例IDE,如果你用其他惯用IDE也可以找到类似的操作方式。
先创建一个工程,从上面罗列出来的架构开始实现。一个一个类的慢慢写,直到写完全部的平台内容。 Idea这个IDE提供了一些预先构建好的KMP模型应用,我们可以直接使用。不过为了更好的学会内容,我们就先从头开始写吧。
打开IDEA,点击 File > New Project(我的是英文环境,中文类似)。
填上你自己的项目名字就可以运行了。
模块
创建好项目后,第一件事儿,就得创建一下不同的module: common
、android
、desktop
、web
。我们就从最基本的common
开始写,写好了其他module也可以依赖它。
这时候直接在根目录右键,new module,选择compose MultiPlatform。直接就可以创建相关的模块
创建成功的效果如下:
修改根目录的gradle.properties
文件如下:
kotlin.code.style=official
android.useAndroidX=true
kotlin.mpp.enableGranularSourceSetsMetadata=true
kotlin.native.enableDependencyPropagation=false
android.enableJetifier=true
这个时候编译应该会很漫长,可以先等待,稍后我们会开始创建数据源集合。
数据集
因为compose的模板已经创建好了相关文件夹,但是需要思考一个问题:
不是说common模块应该是跨平台的嘛?为什么还要在里面创建desktop和android?
可以假定一个虚构的使用场景:你正在开发一个跨平台的app,但是你也需要获取到一些,不同平台特有的API。比如:获取系统版本,连接到底层的日志系统,或者是生成随机的uuid等功能。
KMP还是允许一些简单的方式去获取上面这些底层架构功能的嗯。你可以像如下操作:
// Under Common
expect fun randomUUID(): String// Under Android
import java.util.*
actual fun randomUUID() = UUID.randomUUID().toString()// And so on for all other platforms
当然了,这些复杂的底层操作在我们的简单demo中并不会用到~
回到我们的项目中。
可以注意一下我们的compose跨平台module中的 settings.gradle.kts
的文件内容
pluginManagement {
repositories {
google()
gradlePluginPortal()
mavenCentral()
maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
}
plugins {
kotlin("multiplatform").version(extra["kotlin.version"] as String)
kotlin("android").version(extra["kotlin.version"] as String)
id("com.android.application").version(extra["agp.version"] as String)
id("com.android.library").version(extra["agp.version"] as String)
id("org.jetbrains.compose").version(extra["compose.version"] as String)
}
}
rootProject.name = "composemultidemo"
include(":android", ":desktop", ":common")
作者:issane
链接:https://juejin.cn/post/7197714333475553338