🚀 ニフティ’s Notion

【モバイルアプリ2024 #5】宣言的UIについて/UIの実装

💡
この章で話すこと
  • 宣言的UIという概念
  • Jetpack Composeの概要
  • Material Designの概要

宣言的UIとは

宣言的UIは、UIの状態を直接的に記述するプログラミングパラダイムです。従来の命令型UIとは異なり、宣言的UIはUIの状態がどのように変化するかを記述するのではなく、UIが特定の状態にある場合にどのように見えるべきかを宣言します。

命令的UIプログラミング の例は以下になります。

val linearLayout = LinearLayout()
linearLayout.orientation = VERTICAL

val textView1 = TextView().apply {
    text = "hello"
}
val textView2 = TextVew().apply {
    text = "world"
}
linearLayout.add(textView1)
linearLayout.add(textView2)

コンピューターにViewの作り方を命令していきます。LinearLayoutを作り、TextViewを2つ作り、最初に作ったLinearLayoutにTextViewを追加します。このように、どこに何がaddされるのかコードを全部読むことによってようやく“textview二つが各々上下に配置されるようなUI”だと理解できます。

一方、 宣言的UIプログラミング は下のようになります。

@Composable
fun MyView() {
    Column {
        Text("hello")
        Text("world")
    }
}

どちらの方がわかりやすいでしょうか?理解しやすいプログラミングは場合によって変わってきます。その時にあったより良い実装を選択していきましょう。

Jetpack Compose

Jetpack Compose は、ネイティブ UI をビルドする際に推奨される Android の最新ツールキットです。Android の UI 開発を簡素化し、加速します。少ないコード、パワフルなツール、直感的な Kotlin API を使用してアプリをすぐに動かすことができます。(和訳)
https://developer.android.com/compose
Jetpack Composeの良さ
  • 宣言的アプローチ:UIの状態が変更されると、これらの変更を反映するためにUIが再構築されます。これにより、UIとデータ状態の間の同期を維持するための追加のコードを書く必要がなくなります。
  • コードの削減:Jetpack Composeは、UIを表現するために必要なコードの量を大幅に削減します。これは、UIコンポーネントを直感的なKotlin APIを使用して宣言的に記述できるためです。
  • ツールの統合:Jetpack Composeは、Android Studioとシームレスに統合されており、プレビュー、インタラクティブなプレビュー、デバッグツールなど、強力な開発ツールを提供します。
  • モダンなKotlinに基づく:Jetpack ComposeはKotlinに完全に基づいており、Kotlinの言語機能(例:コルーチン、フロー、ラムダ、型推論など)をフル活用して、より表現豊かでコンパクトなコードを書くことができます。
  • パフォーマンス:Jetpack Composeは、パフォーマンスを最適化するために設計されています。例えば、状態の変化が発生すると、影響を受けるUIコンポーネントのみが再構築されます。
  • マテリアルデザインとの統合:Jetpack Composeは、マテリアルデザインの原則とコンポーネントをネイティブにサポートしています。これにより、一貫性のある視覚的スタイルとユーザーエクスペリエンスを簡単に実現できます。

💡
要約: Jetpack Composeとは?
  • AndroidのネイティブUI開発キット
  • Googleが推奨している
  • 宣言的UI
  • Kotlinで記述する
  • 基本的にステートレス

用語

コンポーザブル

Jetpack Composeでは、UIは全て @Composable でマークされた通常の関数で構築されます。

これらのUIコンポーネントとなる関数を コンポーザブル関数 (コンポーズ可能な関数)と呼びます。

コンポーザブル関数は並列して実行されます。また、アニメーションのフレームごとに何度も実行される場合があるため、コンポーザブルは高速かつ冪等で副作用のないものにすることをおすすめします。

再コンポーズ

コンポーザブル関数を呼び出すことでデータをUIに変換します。

データが更新されるとコンポーザブル関数は再実行され更新されたUIを作成します。

このことを 再コンポーズ と言います。

UIの描写、変更にはコンピューティングリソースと電力が必要です。そのため、再コンポーズでは画面全体を再計算するのではなく、変更された可能性のあるコンポーズのみを呼び出し、残りはスキップすることで効率的に処理されます。

再コンポーズがスキップされることがあるため、コンポーザブル関数は冪等であり、副作用に依存してはいけません。

Jetpack Composeが登場する以前は…

Jetpack Composeが登場する以前、UIはXMLを用いて定義するのが一般的でした。

縦に文字を並べるには以下のように記述します。

<LinearLayout
    ...
    android:orientation="vertical">
    <TextView
				...
        android:text="hello"/>
    <TextView
        ...
        android:text="world"/>
</LinearLayout>

UIを更新するには、KotlinやJavaから findViewById()  などの関数を使用してUIツリーをたどってから button.setText(String) container.addChild(View) などもメソッドを用いてUIの内部状態を変更します。UIが複雑になればなるほど、更新を必要とする要素が増え、メンテナンスが複雑になっていきます。複雑になることで、予期しない変更の競合や存在しない要素を変更しようとしてしまうことが発生し、クラッシュの原因となります。

参考

Material Designとは

Jetpack ComposeではMaterial Designに準拠したコンポーザブル(UIコンポーネント)が提供されています。

Material Designとは、Googleが提唱するデザインガイドラインです。

Material Designにはバージョンがあり、最新はMaterial Design 3です。

Android 12からMaterial Design 3を基にしたデザインが採用されています。

Material Designでは トークン を用いて定義していきます。

トークンにはリファレンストークン、システムトークン、コンポーネントトークンの3種類があります。

ハードコードされた値ではなくトークンを使うことで実装、変更、拡張が効率的にできます。

また、トークンはデザイナーとの共通言語として作用します。