移行戦略

コレクションでコンテンツを整理 必要に応じて、コンテンツの保存と分類を行います。

ビューベースの UI を備えたアプリがある場合、その UI 全体を一度に書き換える必要はありません。このページでは、新しい Compose 要素を既存の UI に追加する方法を紹介します。

Jetpack Compose は、ビューの相互運用性を最初から考慮して設計されています。この機能で、既存のビューベースのアプリを Compose に移行しつつ、新しい機能を引き続きビルドできます。Compose に移行する場合、アプリが完全に Compose に移行されるまで、コードベースに Compose と View を共存させる増分移行をおすすめします。

ビューベースのアプリの Compose への移行段階
図 1. ビューベースのアプリの Compose への移行段階

アプリを Compose に移行するには、次の手順を行います。

  1. Compose を使用して新機能を作成します。
  2. 機能を構築しながら、再利用可能な要素を特定し、一般的な UI コンポーネントのライブラリの作成を開始します。
  3. 既存の機能を 1 画面ずつ置き換えます。

Compose を使用して新機能を作成する

Compose を使用して新機能をビルドすることが、Compose の導入を促進する最良の方法です。この戦略で機能を追加することで、企業のビジネスニーズに対応しながら Compose のメリットを活用できます。

新しい画面

Compose で記述された新しい画面
図 2. Compose で記述された新しい画面

Compose を使用して既存のアプリに新しい機能をビルドする場合でも、アプリのアーキテクチャの制約下で作業を行います。フラグメントと Navigation コンポーネントを使用していて、構築する機能に画面全体が含まれている場合、新しいフラグメントを作成する必要がありますが、その内容は Compose に含まれます。

フラグメントで Compose を使用するには、フラグメントの onCreateView() ライフサイクル メソッドで ComposeView を返します。ComposeView には、コンポーズ可能な関数を提供できる setContent() メソッドがあります。

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.compose.runtime.Composable
import androidx.compose.ui.platform.ComposeView
import androidx.fragment.app.Fragment

class NewFeatureFragment : Fragment() {
   override fun onCreateView(
       inflater: LayoutInflater,
       container: ViewGroup?,
       savedInstanceState: Bundle?
   ): View {
       return ComposeView(requireContext()).apply {
           setViewCompositionStrategy(DisposeOnViewTreeLifecycleDestroyed)
           setContent {
               NewFeatureScreen()
           }
       }
   }
}

詳しくは、フラグメント内の ComposeView をご覧ください。

既存の画面

ビューと Compose が混在する既存の画面
図 3. ビューと Compose が混在する既存の画面

新しい機能が既存の画面の一部になる場合は、他のビューと同様に、ComposeView を UI 階層に追加できます。

たとえば、LinearLayout に子ビューを追加するとします。これは、次のように XML で行うことができます。

<LinearLayout ...>

  <Button ... />

  <TextView ... />

  <androidx.compose.ui.platform.ComposeView
    android:id="@+id/compose_view" ... />

</LinearLayout>

ビューがインフレートしたら、後で階層内の ComposeView を参照して setContent() を呼び出すことができます。

ComposeView について詳しくは、Interoperability API をご覧ください。

一般的な UI コンポーネントのライブラリを作成する

Compose を使用して機能を作成する場合、結果としてコンポーネントのライブラリを構築することになるはずです。共通の UI コンポーネントのライブラリを作成することで、アプリ内のそれらのコンポーネントの信頼できる唯一の情報源を保持して、再利用性を促進できます。作成した機能は、このライブラリに依存させることができます。この手法は、Compose でカスタム デザイン システムを構築する場合に特に便利です。

アプリのサイズに応じて、このライブラリは別個のパッケージ、モジュール、ライブラリ モジュールにすることができます。アプリ内のモジュールを整理する方法について詳しくは、Android アプリのモジュール化に関するガイドをご覧ください。

既存の機能を Compose で置き換える

Compose を使用して新機能を構築するだけでなく、Compose を活用するために、アプリ内の既存の機能を段階的に移行することもできます。

アプリを Compose のみにすることで、開発を加速でき、アプリの APK サイズとビルド時間も短縮できます。詳しくは、Compose のデベロッパー エルゴノミクスをご覧ください。

シンプルな画面

既存の機能を Compose に移行する際にまず確認する必要があるのは、シンプルな画面です。シンプルな画面には、ウェルカム画面、確認画面、設定画面などがあり、UI に表示されるデータは比較的静的です。

次の XML ファイルを使用します。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:orientation="vertical"
   android:layout_width="match_parent"
   android:layout_height="match_parent">

 <TextView
   android:id="@+id/title_text"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:text="@string/title"
     android:textAppearance="?attr/textAppearanceHeadline2" />

 <TextView
     android:id="@+id/subtitle_text"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:text="@string/subtitle"
     android:textAppearance="?attr/textAppearanceHeadline6" />

 <TextView
     android:id="@+id/body_text"
     android:layout_width="wrap_content"
     android:layout_height="0dp"
     android:layout_weight="1"
     android:text="@string/body"
     android:textAppearance="?attr/textAppearanceBody1" />

 <Button
     android:id="@+id/confirm_button"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:text="@string/confirm"/>

</LinearLayout>

この XML ファイルは、Compose で数行で書き直すことができます。

@Composable
fun SimpleScreen() {
    Column(Modifier.fillMaxSize()) {
        Text(
            text = stringResource(R.string.title),
            style = MaterialTheme.typography.h2
        )
        Text(
            text = stringResource(R.string.subtitle),
            style = MaterialTheme.typography.h6
        )
        Text(
            text = stringResource(R.string.body),
            style = MaterialTheme.typography.body1
        )
        Spacer(modifier = Modifier.weight(1f))
        Button(onClick = { /* Handle click */ }, Modifier.fillMaxWidth()) {
            Text(text = stringResource(R.string.confirm))
        }
    }
}

ビューと Compose が混在する画面

少量の Compose コードがすでに含まれている画面も、Compose に完全に移行する候補として有力です。画面の複雑さに応じて、完全に Compose に移行することも、部分的に移行することもできます。UI 階層のサブツリーで Compose が実行された画面は、画面全体が Compose になるまで UI 要素の移行が続けられます。このアプローチは、ボトムアップ アプローチとも呼ばれます。

ビューと Compose の混合 UI を Compose に移行するボトムアップ アプローチ
図 4. ビューと Compose の混合 UI を Compose に移行するボトムアップ アプローチ

フラグメントと Navigation コンポーネントを削除する

アプリの UI がすべて Compose に入ると、アプリでフラグメントを使用するメリットがほとんどなくなります。ここまで来ると、Fragment を完全に削除し、代わりに Navigation Compose によって駆動される画面レベルのコンポーザブルに置き換えることができます。

詳しくは、Compose を使用したナビゲーションをご覧ください。

次の手順

Compose をアプリに追加する方法を詳しく確認する場合は、Jetpack Compose をアプリに追加するをご覧ください。また、次のリソースもご覧ください。