LoginSignup
4
2

More than 1 year has passed since last update.

Jetpack Compose Beta Overviewの動画を見たのでまとめる

Last updated at Posted at 2021-05-13

注意

  • 本記事はYouTubeのAndroid Developersチャンネルにおいて投稿された動画である Jetpack Compose: Beta overviewについて、動画内で述べられていることと、一部筆者の主観が入っている記事となっております。
  • 記事内で使用される画像は、Jetpack Compose: Beta overviewより引用させていただいております。(不都合等ありましたらコメントをお願いします)
  • 動画を全範囲網羅している記事ではありません。

Jetpack Composeとは?

1. Modern, declarative UI tool kit

  • Composeは、宣言的UIを可能にするUIツールキット。
  • 宣言的UIとは?
    • どのように見えるか(What)を記述し、どのように作るか(How)を記述しない

2. Built on Kotlin

  • Kotlinで作られており、Composeの関数のような、直感的なAPIを構築するのに十分な表現力

3. Unbundled

  • Composeは他のJetpackライブラリと同様にアンバンドルされています。
  • プロジェクトのペースで更新できるように、APIバージョン間で一貫した動作をする
  • アンバンドルとは?
    • Androidのプラットフォームに含まれておらず(unbundle)、ライブラリとして追加できる

4. Built for interop

  • 相互運用(interop)を重視している
  • 例えば、新規の画面から徐々にComposeに移行することができるみたいな

現在のJetpack Composeの状況

  • Jetpack Composeは現在Betaである(2021/04/15時点)
  • APIの洗練と安定化に焦点を当てて開発中

Jetpack Composeの推しポイント

  • ComposeはAndroidのUIをよりはやく・簡単に実装することができる
  • なぜ、はやく・簡単に実装することができるのか?
    • 宣言的とUIツールの2つに分解して説明していく

まず宣言的について

従来のアプローチ(慣例的なアプローチ)

上の図の例は、入門書などに書かれている一般的な例。

XMLがあり、その状態を変更するために、findViewById()などをして、プロパティを設定する。

例えば、DBやネットワークから情報をActivity・Fragmentが受け取ったとき、その情報をもちいてUIを更新するなど。

この問題点はStateがXMLとFragment/Activityの両方に存在すること。

例えば、上図のTextViewのテキストをAPIの結果に応じて変化させる場合を考える。

XMLのレイアウトファイルにTextViewがあり、初期のテキストが設定されているとする

そして、APIの結果として、文字列を受け取ったときにその情報を格納する変数をFragment・Activityに定義していたとする。

TextViewの状態、Fragment・Activityの状態の2つが存在する。

Fragment・Activity間の状態を、TextViewの状態に反映するには、setText()などを使用しなければいけない。

この手続き的な操作は、開発者の責任で行う必要があり、バグの原因となってしまう。

JetPack Composeのアプローチ

上図のようにStateとUIがあり、Stateは変化するもので、UIは普遍で変更されないもの。

状態が変化した際に、UI全体が再生成される(効率化のために実際には差分のみの再生成となる)

先ほどの例(TextViewのテキストをAPIの結果に応じて変化させる場合)について考えてみる。

状態はFragment・Activityで保持する1つのみとなり、状態としてTextViewに表示する文字列が入っている。

APIリクエストがあり、状態の変更を検知して、状態をもとにUIを再生成する。

何が良いのか?

これにより、状態に応じて自動的にUIが変更されることになる。
例えば、先ほどの例でいうところの、setText()という手続きが不要になる。

結果として、手続きの記述漏れなどによるバグがなくなる。

コードレベルで確認していく!

  • 上記コードの説明
    • 文字列のリストを表示する単純なコンポーネント
    • 関数は何も返さないが、UIをemitする
    • messageの中身が空の場合は「No messsages」を、それ以外の場合はメッサージをテキストとして表示
    • 関数が実行されたら、新しいUIが作成される
    • これをRecomposingと呼ぶ。メッセージの状態が変わったら、UIが再生成される
messageの変化をどう検知するのか?

messageをLiveDataとする。

  • 上記のコードの説明
    • ViewModelにおいて、messageをLiveDataで公開
ConverationViewmodel.kt
  // おそらくこんな感じ
  class ConversationViewModel: ViewModel() {

    private val _message = MutableLiveData("")
    val message: LiveData<String> = _message
                :
  • LiveDataで新しいデータを検知するたびにMessageList(message)が呼ばれUIが再生成される
  • 注意点
    • Composableはimmutableなので、参照を保持して、後で照会したり、内容を更新することはできない
    • したがって、全ての情報をEmit時にパラメーターとして渡す必要がある
しかしながら、コンポーネントが変化できないということを意味するわけではない

すべてのメッセージを選択するチェックボックスを追加して、すべてのメッセージを選択できるようにしてみる。

上記のコードだと、チェックボックスをクリックしても視覚的には切り替わらない。(cheched = false)としているので。

なので、状態を更新して、チェックボックスをemitする必要がある

どうするか?
チェックするかどうかのローカルな状態を持たせる。

そして、CheckBox()のパラメータonCheckChangeにユーザがチェックしたときのコールバックを設定する。

このようにすることで、チェックボックスの状態であるselectAllがクリック時に更新され、チェックボックスへ視覚的な状態が反映される。

しかしこれだと、UIにロジックがあって気持ち悪い
下記のように、MessageList()のパラメータとして、ステートと更新のためのラムダを渡す。

Composeはどういうアーキテクチャが適しているか?

基本的には、Composeはどのようなアプリケーション・アーキテクチャにも対応できる。

特に一方向性のデータ・フローとの相性が良く、ViewModelが画面の状態のストリームを公開しているとき。

各コンポーネントはパラメーターとして状態を受け取り、データが更新された場合にのみUIを更新する。

1つのLiveDataを使用することで、状態を一元化でき、画面全体の状態についての理解が簡単になりエラーを減らせる。

宣言的についてのまとめ

Composeを使用すると Single Source Of Truth(信頼できる唯一の情報源) の原則が守れる。

慣習的なアプローチでは、Fragment・Activityで保持している状態とViewが保持している状態の2つがあり、バグの原因となる可能性があった。

しかし、Composeを使用すると状態を一元管理することができる。

そして「状態に変化があったときに、自動でUIが変更される」という性質により、バグが生まれにくくなる。

UIツールについて

ComposeはUIコンポーネントの豊富なツールキットを提供している。

機能やメリット

Material Design ComponentとMaterial Themingのサポート
Material Design Component Material Theming
image.png image.png
シンプルだがパワフルなレイアウトシステムを提供

例えば、RowというComposableは、LinearLayoutのorientationhorizontalに指定したレイアウトとほぼ同等。
しかし、Viewシステムが異なり、ネストされたレイアウトをパフォーマンスの高いものにしてくれるメリットがある。

image.png

より複雑なレイアウトを表現するために、ConstraintLayoutも提供されている。
image.png

ただし、カスタムレイアウトを使う方が簡単。
image.png

アニメーションシステム

UIに動きをつけることが、より使いやすく、非常にパワフルになっている。
MotionLayoutをComposeに導入する作業も行っている
image.png

テスト

Composeは、テストを容易にするために専用のテストシステムを提供する。
そして、Composablesを個別にテストするための簡単なAPIを提供する。
アニメーションのテストも書くことができる。
image.png

Kotlinで書かれている

Kotlinの優れた言語機能のおかげで、シンプルで直感的なAPIとなっている。
例えばCoroutineを使用することによって、シンプルな非同期APIを作成できるようにしている。
Coroutineを使用して、タッチ検出がブロックされないように、新しいコルーチンで押された位置にアニメーションさせている。
image.png

具体例で確認していく!

下記レポジトリの中のJetchatというアプリで説明。
https://github.com/android/compose-samples

レイアウトの説明

image.png

上記のレイアウトを作るには下記のことを行っている

  • message(=表示するテキスト)、isFromMe(=自分からのメッセージがどうかのフラグ)をパラメータに持つComposableを作成
  • メッセージ全体を囲むCard Composableを作成
    • isFromMeに応じて、Themeから色を指定
  • 実際にテキストを表示するためにText Composableを作成
    • Modifierパラメータ用いてpaddingを設定
開発・検証方法

@Previewアノテーションを用いてプレビュー用のComposableを作成する。
それをAndroid Studio上で確認することが可能
image.png

この後、細かい実装方法が紹介されているので割愛。
述べられている内容

  • ComposableのパラメータにModifierを渡して、再利用可能に
  • Modifierでは、最大幅やテキストのAlignmentなどを指定
  • LazyColumnを使用してRecyclerViewのような効率的なスクロールの実装
  • など

興味ある方は、10:3312:59

推しポイントまとめ

宣言的なUIによって、Composeを使用するとSingle Source Of Truth(信頼できる唯一の情報源)の原則が守れる。
UIツールによって、レイアウトやアニメーションの実装が簡単になる。
-> 簡単に、はやく実装することができる

まだまだ推しポイントはある

既存のViewシステムと共存できる

image.png

Interoperability APIと呼ばれるものが用意されている

:
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">
                      :
    <androidx.compose.ui.platform.ComposeView
        android:id="@+id/compose_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
                      :
</LinearLayout>
class ExampleFragment : Fragment() {

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        // Inflate the layout for this fragment
        return inflater.inflate(
            R.layout.fragment_example, container, false
        ).apply {
            findViewById<ComposeView>(R.id.compose_view).setContent {
                // In Compose world
                MaterialTheme {
                    Text("Hello Compose!")
                }
            }
        }
    }
}

コードの引用: https://developer.android.google.cn/jetpack/compose/interop?hl=ja#interop-apis

他の主要なライブラリとの統合を提供

image.png

資料等

image.png

Composeの学習系

フィードバック等

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2