Webエンジニア「Kotlin」を学ぶ 〜JetpackCompose編〜

前回以下の記事でKotlinがどのような言語なのかを学びました。
この記事ではAndroidアプリ開発で使用されるJetpack Composeについて備忘録としてまとめています。

https://qiita.com/Otohu_mimizu/items/17e66e868ae84b53825c

# JetpackComposeとは？
まずはそもそもJetpack Composeが何なのかを[公式ドキュメント](https://developer.android.com/codelabs/jetpack-compose-basics?hl=ja#0)で確認

> Jetpack Composeは、UI開発を簡素化するために設計された最新のツールキットです。リアクティブ プログラミング モデルに、Kotlin プログラミング言語の簡潔さと使いやすさを組み合わせています。完全な宣言型であるため、データを UI 階層に変換する一連の関数を呼び出すことにより UI を記述します。基になるデータが変更されると、フレームワークは自動的にそれらの関数を再実行して UI 階層を更新します。

ちょっとわかりにくかったのでChatGPTに聞いてみると以下のメリットを享受できるようです。

- 従来のXMLベースでのUI構築に比べて、レイアウトデザインに必要なコード量が大幅に少なくなり、UIの設計と更新がシンプルになる
- UI定義とロジックが同じ場所に記述されるため、設計と更新が行いやすくなるメリットがある
- アニメーション専用の関数やツールが用意されているため、複雑なアニメーションも少ないコードで実現できる

### XMLとJetpack Composeでどれくらいコード量に差があるのか？
- XMLでの実装

``` xml
<!-- res/layout/activity_main.xml -->
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:gravity="center"
    android:padding="16dp">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Count: 0"
        android:textSize="24sp" />

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Increment" />
</LinearLayout>

```

``` kotlin
// MainActivity.kt
import android.os.Bundle
import android.widget.Button
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity

class MainActivity : AppCompatActivity() {

    private var count = 0

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val textView = findViewById<TextView>(R.id.textView)
        val button = findViewById<Button>(R.id.button)

        button.setOnClickListener {
            count++
            textView.text = "Count: $count"
        }
    }
}
```

xmlでの実装はUIの記述とActivityの2つのロジックを別ファイルに定義する必要があるため、開発時の見通しが悪く、管理が複雑になってしまう。
- Jetpack Composeでの実装
```kotlin
// MainActivity.kt
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.*
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            CounterApp()
        }
    }
}

@Composable
fun CounterApp() {
    var count by remember { mutableStateOf(0) }

    Column(
        modifier = Modifier
            .fillMaxSize()
            .padding(16.dp),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Text(text = "Count: $count", fontSize = 24.sp)
        Spacer(modifier = Modifier.height(16.dp))
        Button(onClick = { count++ }) {
            Text(text = "Increment")
        }
    }
}
```

宣言型UIにより、１ファイル内でUIとロジックを管理することができるため、状態管理が簡単になる。

# Composeを使用するには？
`@Composable`アノテーションを付けることでコンポーズ可能な関数を定義できる。
実際に自動生成されたものを確認してみると以下のように定義されている。
ここでは`Greeting`関数をコンポーズしており、ライブラリで提供される`Text`関数を使用して画面にテキストを表示させている。

``` kotlin
@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
    Text(
        text = "Hello $name!",
        modifier = modifier
    )
}
```

# まとめ
Jetpack Composeを使用することでUIとロジックを簡単に定義できるのは非常に開発効率が良いと感じた。Android Studioではリアルタイムプレビュー機能も用意されているため、IDEとブラウザを切り替えることなく、動作を確認することができる点も便利だと感じた。
まだ、Kotlinを学習し初めて間もないがこれまで触ってきたPythonやRubyなどに比べて開発が楽しいと感じました。