安定性に関する問題を解決する

クラスが不安定でパフォーマンスが発生した場合 安定版にすべきですこのドキュメントでは、Google Cloud で できます。

強力なスキップを有効にする

まず、強力なスキップモードを有効にしてみてください。強スキップモード 不安定なパラメータを持つコンポーザブルをスキップできます。これは、 メソッドです。

詳しくは、強いスキップをご覧ください。

クラスを不変にする

不安定なクラスを完全に不変にすることもできます。

  • 不変: プロパティの値を取得できない型を示します。 その型のインスタンスが作成された後に変更され、すべてのメソッドが 参照します。
    • クラスのすべてのプロパティが var ではなく val であることを確認します。 不変型です
    • String, IntFloat などのプリミティブ型は常に不変です。
    • これが不可能な場合は、Compose の状態を使用して 削除することもできます。
  • Stable: 可変型を示します。Compose ランタイムは その型のパブリック プロパティまたはメソッドのいずれかが、 前の呼び出しとは異なる結果が得られます。
で確認できます。

不変のコレクション

Compose がクラスを不安定とみなす一般的な理由は、コレクションです。前述のとおり [安定性の問題を診断する] ページ(Compose コンパイラ) List, MapSet などのコレクションが、 変更不可とマークされ、不安定な状態としてマークされます。

この問題を解決するには、不変のコレクションを使用します。Compose コンパイラ には、Kotlinx の不変コレクションのサポートが含まれています。これらの コレクションは不変であることが保証されており、Compose コンパイラはそれらを できます。このライブラリはまだアルファ版であるため、API が変更される場合があります。

安定性の診断」セクションの不安定なクラスについて、もう一度考えてみましょう。 問題に関するガイド:

unstable class Snack {
  
  unstable val tags: Set<String>
  
}

不変のコレクションを使用して、tags を安定版にすることができます。クラスで、 tags から ImmutableSet<String> への型:

data class Snack{
    
    val tags: ImmutableSet<String> = persistentSetOf()
    
}

そうすると、クラスのすべてのパラメータは不変になり、Compose は コンパイラがクラスを安定版としてマークします。

Stable または Immutable でアノテーションを付ける

安定性の問題を解決するには、不安定なクラスにアノテーションを付けることをおすすめします。 @Stable または @Immutable に置き換えます。

クラスにアノテーションを付けると、コンパイラによるアノテーションがオーバーライドされる 推論できます。これは、 Kotlin の !! 演算子。あなたは アノテーションの使い方に注意してください。コンパイラ動作のオーバーライド コンポーズ可能な関数が再コンポーズされないなど、予期せぬバグを 確認します。

アノテーションなしでクラスを安定させることができる場合は、 安定性が確保される場合があります。

次のスニペットは、 immutable:

@Immutable
data class Snack(

)

@Immutable アノテーションと @Stable アノテーションのどちらを使用する場合でも、Compose コンパイラ Snack クラスが安定版としてマークされます。

コレクション内のアノテーション付きクラス

List<Snack> 型のパラメータを含むコンポーザブルについて考えてみましょう。

restartable scheme("[androidx.compose.ui.UiComposable]") fun HighlightedSnacks(
  
  unstable snacks: List<Snack>
  
)

Snack@Immutable アノテーションを付けても、Compose コンパイラはマークします。 HighlightedSnackssnacks パラメータが不安定です。

コレクション型については、パラメータはクラスと同じ問題に直面します。 Compose コンパイラは、場合でも List 型のパラメータを常に不安定としてマークする それが安定した型のコレクションである場合です

個々のパラメータを安定版としてマークしたり、注釈を付けたりすることはできません。 常にスキップ可能にします進むべき道は複数あります。

不安定なコレクションの問題を回避するには、いくつかの方法があります。 以降のサブセクションでは、これらのさまざまなアプローチの概要を説明します。

構成ファイル

コードベースの安定性に関する契約に従う場合は、 Kotlin コレクションを安定版と見なすことを有効にするには、 kotlin.collections.*安定性構成ファイル

不変のコレクション

不変性をコンパイル時の安全性を確保するために、 List の代わりに kotlinx のイミュータブル コレクションを使用します。

@Composable
private fun HighlightedSnacks(
    
    snacks: ImmutableList<Snack>,
    
)

Wrapper

不変のコレクションを使用できない場合は、独自のコレクションを作成できます。そのためには、 アノテーション付きの安定版クラスで List をラップします。汎用ラッパーは多くの場合、 最適な選択肢を選びます

@Immutable
data class SnackCollection(
   val snacks: List<Snack>
)

これをコンポーザブルのパラメータの型として使用できます。

@Composable
private fun HighlightedSnacks(
    index: Int,
    snacks: SnackCollection,
    onSnackClick: (Long) -> Unit,
    modifier: Modifier = Modifier
)

解決策

これらのアプローチのいずれかを採用すると、Compose コンパイラは HighlightedSnacks コンポーズ可能な関数を skippablerestartable の両方として。

restartable skippable scheme("[androidx.compose.ui.UiComposable]") fun HighlightedSnacks(
  stable index: Int
  stable snacks: ImmutableList<Snack>
  stable onSnackClick: Function1<Long, Unit>
  stable modifier: Modifier? = @static Companion
)

再コンポーズの際に、Compose が HighlightedSnacks をスキップできるようになりました。 確認します。

安定性構成ファイル

Compose Compiler 1.5.5 以降では、 がコンパイル時に提供可能であると見なします。これにより 標準ライブラリ クラスなど、自分で制御していないクラス LocalDateTime などが安定版です。

構成ファイルは、1 行に 1 つのクラスを含む書式なしテキスト ファイルです。コメント 単一および二重のワイルドカードがサポートされています。 構成の例を以下に示します。

// Consider LocalDateTime stable
java.time.LocalDateTime
// Consider kotlin collections stable
kotlin.collections.*
// Consider my datalayer and all submodules stable
com.datalayer.**
// Consider my generic type stable based off it's first type parameter only
com.example.GenericClass<*,_>

この機能を有効にするには、構成ファイルのパスを Compose に渡します。 オプションを提供します。

Groovy

kotlinOptions {
    freeCompilerArgs += [
            "-P",
            "plugin:androidx.compose.compiler.plugins.kotlin:stabilityConfigurationPath=" +
                    project.absolutePath + "/compose_compiler_config.conf"
    ]
}

Kotlin

kotlinOptions {
  freeCompilerArgs += listOf(
      "-P",
      "plugin:androidx.compose.compiler.plugins.kotlin:stabilityConfigurationPath=" +
      "${project.absolutePath}/compose_compiler_config.conf"
  )
}

Compose コンパイラはプロジェクト内の各モジュールで個別に実行されるため、次のことができます。 必要に応じてモジュールごとに異なる構成を提供します。または、1 つの 構成ファイルを作成し、そのパスを各プロジェクトの 説明します。

複数のモジュール

もう一つの一般的な問題は、マルチモジュール アーキテクチャです。Compose コンパイラ クラスが安定しているかどうかを推測できるのは、そのすべての非プリミティブ型が 参照は、stable として明示的にマークされているか、 Compose コンパイラでもビルドできます。

データレイヤーが UI レイヤーとは別のモジュールにある場合、 という問題があるかもしれません。

解決策

この問題を解決するには、次のいずれかの方法を使用できます。

  1. コンパイラ構成ファイルにクラスを追加します。
  2. データレイヤー モジュールで Compose コンパイラを有効にするか、クラスにタグを付ける 必要に応じて @Stable または @Immutable に置き換えます。
    • これには、データレイヤーへの Compose の依存関係の追加が含まれます。ただし、 Compose ランタイムの依存関係にすぎず、 Compose-UI
  3. UI モジュール内で、データレイヤー クラスを UI 固有のラッパーでラップする 。

外部ライブラリが Compose コンパイラ。

すべてのコンポーザブルをスキップ可能にすべきではない

安定性に関する問題を修正する場合、すべての変更を スキップ可能実施しようとすると、時期尚早な最適化につながる可能性があります。 修正するよりも多くの問題を引き起こしかねません。

スキップ可能にしても実際にはメリットがないケースは数多くあります コードの保守が困難になります例:

  • 再コンポーズの頻度が低い、またはまったく再コンポーズされないコンポーザブル。
  • それ自体がスキップ可能なコンポーザブルを呼び出すだけのコンポーザブルです。
  • コストの高い等しいパラメータが多数あるコンポーザブル あります。この場合、パラメータが存在するかどうかを 安価な再コンポーズのコストを上回る可能性があります。

コンポーザブルがスキップ可能の場合、多少のオーバーヘッドが発生します。 できます。コンポーザブルにアノテーションを付けて、再起動不可にすることもできます。 再実行可能であることに気付いたら、