Compose を使用して iOS で動的なアイランド効果を実現する

序文

昨年の DevFest の Compose Camp イベントでは、fundroid と Zhu Jiang の 2 人の講師が全員に Compose を使用してスマート アイランドの効果を実感させました。

しかし、スマート アイランドは結局のところ iOS の機能です。ちょうど今年、KotlinConf で Compose-iOS がすでにアルファ版であることが発表されました。そこで、Compose で実装されているスマート アイランド効果を iOS に移植したらどうなるでしょうか?

考えるのは素晴らしいことです。実際に実行して、Jetpack Compose から Compose Multiplatform にコードを移行するのに何が必要か、そしてそのコストがどれくらいかかるかを確認してください。

結果を示す

まずエフェクトを見ると、スマートアイランドスイッチのアニメーションエフェクトが基本的に実現されていることがわかります。これは基本的にAndroidでのエフェクトと同じです。

実装手順

環境構成

Compose MultiPlatformで開発するには以下の環境が必要です

  • Xコード
  • Androidスタジオ
  • Kotlin マルチプラットフォーム モバイル プラグイン
  • Cocoapods 依存関係マネージャー

実際、これは Kotlin Multiplatform で必要な環境と一致しています。最も面倒なことは、Cocoapods のインストールかもしれません。Cocoapods のインストールについては、KMM ドキュメントを確認できます。CocoaPods で動作する環境のセットアップを確認してください

また、kdoctor環境設定が正しいかどうかはコマンドで確認することもできます。

brew install kdoctor // 安装 kdoctor
kdoctor // 检查

すべての環境が正しく構成されている場合は、次の出力が表示されます。

Environment diagnose (to see all details, use -v option):
[✓] Operation System
[✓] Java
[✓] Android Studio
[✓] Xcode
[✓] Cocoapods

Conclusion:
  ✓ Your system is ready for Kotlin Multiplatform Mobile development!

プロジェクトを作成する

Compose Multiplatform プロジェクトは実際にいくつかの Compose コンテンツを KMM プロジェクトに追加していますが、まだ多くのテンプレート コードが残っています。JetBrains が提供するプロジェクト テンプレートを直接使用してプロジェクトを生成できます: compose-multiplatform-ios-android- template

如图所示,其实就是一个 KMM 工程的结构,android 项目的入口是 androidApp,iOS 项目的入口是 iosApp,共享代码放在 shared 模块

在 shared 模块中,各个平台共享代码放在 commonMain 目录中,而各个平台的定制代码则放在 androidMain 与 iosMain 中

在这里主要的不同在于,android 平台直接返回了一个 Composable 函数,供 android 层调用,而 iOS 平台则返回了一个 UIViewController

代码移植

在项目创建完成后,接下来就是代码移植的工作了。移植过程可以说是非常简单,基本上不用做任何改动,Jetpack Compose 项目就可以迁移成 Compose Multiplatform 项目

在我迁移过程中碰到的唯一不同在于资源文件的处理,如下所示,R 文件引用方式需要修改成字符串方式引用

// Jetpack Compose
Image(
    painterResource(R.drawable.icon_cover),
    "music cover",
    Modifier
        .size(animationData.musicImageSize)
        .clip(RoundedCornerShape(animationData.musicImageCorner))
)

// Compose Multiplatform
Image(
    painterResource("icon_cover.xml"),
    "music cover",
    Modifier
        .size(animationData.musicImageSize)
        .clip(RoundedCornerShape(animationData.musicImageCorner))
)

除此之外,两者的状态管理,布局,动画等 api 是完全一致的,可以直接复用代码

经过以上步骤,迁移就完成了,直接运行 androidApp 与 iosApp 就可以得到文章开始展示的效果了

正在处理中的问题

当然,现在 Compose Multiplatform 还处在 alpha 阶段,并不是说已经可以用于生产了,还有不少问题正在处理中

待支持的功能

图片来源:Compose Multiplatform on iOS by: Sebastian Aigner and Nikita Lipsky

可以看出,Compose Multiplatform 还是有不少细节问题要处理的

性能问题

我们打开 XCode 的 instruments 然后运行 app,就可以得到运行的 trace 文件,统计出运行次数较多或者比较耗时的方法

p7.jpg

可以看出,耗时方法有相当一部分是 GC 相关的,当 GC 暂停发生时,会冻结所有对象,自然也会影响 UI 的渲染,导致卡顿

好消息是 Kotlin 正在优化 GC,期望将 GC 暂停控制在 1 到 2 ms 之内

总结

可以看出将 Jetpack Compose 版的灵动岛迁移到 Compose Multiplatform 的成本是非常低的,最耗时的部分可能是配环境的部分,两者的 API 基本上是一致的,因此代码可以无缝复用

Compose 跨平台补全了 Kotlin 跨平台只支持共享逻辑不支持共享 UI 的短板,降低了 Kotlin 跨平台的开发成本,总得来说,未来可期,希望 Jetbrains 能早日推出正式版

示例代码

本文所有代码可见:github.com/RicardoJian…

参考资料

Compose Multiplatform on iOS by: Sebastian Aigner and Nikita Lipsky

おすすめ

転載: juejin.im/post/7235547967113035813