最近デスクトップアプリを作りたいと思い、最初はWindowsだけでいいかとおもってUWPで作ろうと思っていたが、自分がAndroidエンジニアなこともあり、せっかくならCMPで作ってみようと思って作ったが意外とそんなに困ることがなく、OSにそこまで依存しないアプリならこれでもいいのではとなったお話
目次
DB周り
DesktopでもRoomを使うことが可能です。
具体的には、androidと違いContextを渡しますが、desktopではfileを渡します。
fun getDatabaseBuilder(): RoomDatabase.Builder<AppDatabase> {
val dbFile = File(System.getProperty("java.io.tmpdir"), "my_room.db")
return Room.databaseBuilder<AppDatabase>(
name = dbFile.absolutePath,
)
}
これ以外の違いはあんまりなく、通常通り使えば使用できます。
Paging周り
Pagingについては少々癖があります。
androidのpagingライブラリはkmpには対応していますが、cmpには対応していません。
つまり、
-
androidx.paging:paging-common
<- 使用可能 -
androidx.paging:paging-compose
<- 使用不可能
ということです。
じゃあ、Composeで使う場合Pagingは自分で実装しなきゃいけないじゃん
一応CashAppからmultiplatform-pagingというライブラリが出ており、そちらを使用することが可能です。
こちらのライブラリは、AndroidXのPagingにMultiPlatform用の処理を追加したり、ios用のpaging-uikit
などを追加したりするライブラリになっています。
READMEのInteroperability with AndroidX Pagingを見ていただくとpaging-common
の実装は同じであり,AndroidXのpagingライブラリと相互運用も可能と書いてあります(Paging3に限る)。
そのため、KmpとしてPaging3ですでに書いてあってもrefactorする必要はなく、CMPで使用したい場合は、cashappのpaging-compose-common
を追加して、実装することが可能です。
# これが可能
androidx-paging-common = { group = "androidx.paging", name = "paging-common", version.ref = "androidx-paging" }
cashapp-paging-compose = { group = "app.cash.paging", name = "paging-compose-common", version.ref = "paging-compose" }
File指定
Desktopアプリでは、たびたびFileを指定して何かをすることが多々あると思います。自分で作るとだいぶめんどうな部類の話になると思いますが、Filekitを使うと特にそこまで困ることはなく実装できます。
※一応beta段階なので今後に期待
// main.ktのapplication内
FileKit.init(appId = "MyApplication")
// compose内
val launcher = rememberFilePickerLauncher(
mode = FileKitMode.Multiple(),
type = FileKitType.Image,
) { files ->
// file listが帰ってくる
}
// file選択の実行
launcher.launch()
これでFile選択を実装することができます。modeやtypeなどは必要に応じて指定するとUserが指定したfileを取得することができます。
Mouse操作
Mouse操作に関してもExperimentalではあるものの実装できます。
- Mouseの移動イベント
Box(
modifier = Modifier
.onPointerEvent(PointerEventType.Move) {
val position = it.changes.first().position
}
){}
- MouseのHoverイベント
Box(
modifier = Modifier
.onPointerEvent(PointerEventType.Enter) {
// hover
}
.onPointerEvent(PointerEventType.Exit) {
// leave
},
){}
- MouseのScrollイベント
Box(
modifier = Modifier
.onPointerEvent(PointerEventType.Scroll) {
val dy = it.changes.first().scrollDelta.y
}
){}
- MouseのDrugイベント
Box(
modifier = Modifier
.onDrag {
val offset: Offset it
}
){}
まとめ
新しくアプリを作るのであれば、CMPという手段もなしではないと思う。
しかし、Win32APIなどOSのAPIを使用したりする場合、C Interopなどを実装しなくては行けなく、自分なら使わないかなぁと思う。
意外とそこまで困ることもそんなになくいけんくない
使ったっていいし、使わなくったっていい