目的

AndroidアプリでのUI実装は、ワタシの中での通例はxmlファイルで設定しますが。
今回は、Jetpack ComposeというAndroid公式ライブラリ・ツールを使って、UIをコードで構築したいと思います。
今回はJetpack Composeを使えるようにするのと、画面中央に*Hello world!*と表示するだけです。

ちなみにJetpack Compose自体は2019年に発表されたようで、これのことを宣言型UI手法と言うそうです。

iOSにおけるSwiftUIのようなものとの認識ですが、この記事ではそれと比較などは行いません。

環境

  • ライブラリ等は、2012年10月4日時点でのほぼ最新バージョン
  • Android Studio Bumblebee | 2021.1.1 Canary 13

公式としては上記バージョンがリンクされていて、推奨なのだろうか、まだpreview版です。
今回は上記を利用。
ただAndroid Studio Arctic Fox | 2020.3.1でも動作することは確認した。2020.3.1以上でないと駄目なよう。
Android Studio 4.1.1だとエラーでアップデートしてくれと怒られました。

Android Studio ビルドエラー
This version of the Android Support plugin for IntelliJ IDEA (or Android Studio) cannot open this project, please retry with version 2020.3.1 or newer.





参照サイト

developers JETPACK
GitHub android/compose-samples
stack overflow Jetpack Compose - Column - Gravity center

プロジェクト作成

まずは新規プロジェクトを作成します。
今回はEmpty Activity・空プロジェクトで作成してみます。

この辺はデフォルトままとか適切に設定しますが、Minimum API level21以上を選択する必要があるよう。

ちなみにですが、Empty Activityではなく、Empty Compose Activityを選択もできます。
Empty Activityからやると、build.gradle周りでエラー対応が面倒なので、試すだけなら圧倒的にこちらがおすすめ。


その場合はすでにJetpack Composeで書かれたプロジェクトができて、すぐに実行できます。

今回はxmlと比較したいので、Empty Activityで進めます。





xml形式でのプロジェクトの場合

以下のようになります。

MainActivity.kt
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle

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

activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

実行時は以下。





Jetpack Composeに置き換える

ココからが本題で、上記のxmlの部分をJetpack Composeで置き換えたいと思います。

build.gradle(:app)の設定

まずは*build.gradle(:app)*の設定です。
内容としては

  • minSdkが21以上であること
  • android構文にbuildFeaturesを追記した
  • android構文にcomposeOptionsを追記した
  • dependencies構文については丸ごと書き直した

上記を追加しました。
参照サイトのは少し古いようで、内容若干違います。
Empty Compose Activityの内容に似せています。特にdependencies構文のトコロ

android {
    ...

    defaultConfig {
        ...
        minSdk 21
        ...
    }

    ...

    //以下を追記
    buildFeatures {
        compose true
    }

    //以下を追記
    composeOptions {
        kotlinCompilerExtensionVersion '1.0.3'
    }

    ...
}


dependencies {
    //Empty Compose Activityを参照して追加
    implementation 'androidx.core:core-ktx:1.6.0'
    implementation "androidx.compose.ui:ui:1.0.3"
    implementation "androidx.compose.material:material:1.0.3"
    implementation "androidx.compose.ui:ui-tooling-preview:1.0.3"
    implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1'
    implementation 'androidx.activity:activity-compose:1.3.1'
    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
    androidTestImplementation "androidx.compose.ui:ui-test-junit4:1.0.3"
    debugImplementation "androidx.compose.ui:ui-tooling:1.0.3"

    //他のGoogleサンプルを参照して追加
    implementation 'com.google.android.material:material:1.4.0'
    implementation 'androidx.appcompat:appcompat:1.3.1'
}




settings.gradleの設定

あとdependenciesのバージョンによってはkotlinのバージョンを上げろエラーとなる。
settings.gradleにある、org.jetbrains.kotlin.androidのバージョンの変更が必要かも。
今回は以下のようにした。

pluginManagement {
    ...
    plugins {
        ...
        id 'org.jetbrains.kotlin.android' version '1.5.30'
    }
}

上記設定後はSync Nowしてみてエラーが出ないことを確認。

MainActivity.ktの設定

次にMainActivity.ktファイルの修正です。以下とした。
onCreate内のsetContentView(R.layout.activity_main)の記載は削除します。

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material.Text
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier


class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        //setContentViewを消して、以下setContentを追加
        setContent {
            Column(
                Modifier.fillMaxSize(),
                verticalArrangement = Arrangement.Center,
                horizontalAlignment = Alignment.CenterHorizontally
            ) {
                Text(text = "Hello world2!")
            }
        }
    }
}

これで実行すると以下になる。

括弧で増長されているがxmlファイルで書いていたUI部分が、
9行で構成できてしまった。





まとめ

ということで、Jetpack Composeについてでした。
初歩中の初歩の説明です。
まだプレビュー機能とか、コンポーズ化とか必要な説明がありますが、一旦ここまで。

それでココからは自分の意見で、かなり長くなるのですが。

発表から2年ほど経っているようですが、それでもまだ早いと思いました。

過渡期でしょうか、dependenciesのバージョンも頻繁にアップしている気がしますし。
サイトを見ていると記載が微妙に違うトコロもあります。
なによりGoogleの公式ドキュメントでさえ違っているような。
あと、情報量がかなり少ないと思いました。
今回の記事の中央に寄せるだけでもstack overflowしか分かりやすいのがなく。

それと、プレビュー機能も試したのですが、なんかリアルテイムで変更が行われないことが多く、いちいちリロードボタンを押していました。
使いづらいと思いました。

Androidのxmlファイルの形式は、これ自体コードで書いているようなものですし、ワタシはしてはxmlのままでも良いかなという思いなのですが。
Jetpack Composeの紹介の中でのGoogleの人の説明によると、
昨今のアプリは成熟してきて、アニメーションやリアルタイムでの情報更新に重みを置くようになってきているとのことで。

それで、宣言型UI手法でUIは素早く構築することで、他のプログラミングに時間を割ける。
的な言い回しをしていました。
それに、UIの振る舞いとかもコードだけを見れば良い・コードで書いていることが全てとなる。
的なことも言っていました。

なるほどなぁ。