Component for Desktopコード解析

10848 ワード

今回のリリースでは、以前に作成したCounterアプリケーションのコードを分析し、Componentを学習します.
@Composable
fun MainWindow(state: MainWindowState)
Componentを使用するには、データをUI要素に変換する複合関数を定義する必要があります.@Composable宣言を指定することで複合関数を定義できます.Composable関数には、非常に簡単なライフサイクルがあります.初期と再配置の2種類.

Composeは、初期コンパイル時に初めてコンパイルを実行した場合を追跡し、コンパイル中にUIのコンパイルを記述するために呼び出される.その後、アプリケーションのステータスが変更された場合、Componentは再配置を保持します.再配置とは、ステータスの変更に伴って変更される可能性のあるコンポーネントを再実行し、そのコンポーネントを更新して変更を反映することです.
初期位置でのみ作成できますが、再配置でのみ更新できます.ブレンドを修正する唯一の方法は、ブレンドを再ブレンドすることです.
新しい用語が出てきたので混乱しています.まず、例を見てみましょう.
@Composable
fun BadCounter() {
    println("BadCounter: Start")
    var count = 0
    println("BadCounter: count initialize : $count")
    Button(
        onClick = {
            println("BadCounter: count onClick (count: $count)")
            count++
            println("BadCounter: count update (count: $count)")
        }
    ) {
        Text("$count")
    }
}

/* output:
 * BadCounter: Start
 * BadCounter: count initialize : 0
 * BadCounter: count onClick (count: 0)
 * BadCounter: count update (count: 1)
 * BadCounter: count onClick (count: 1)
 * BadCounter: count update (count: 2)
 * BadCounter: count onClick (count: 2)
 * BadCounter: count update (count: 3)
**/
これは、コンパイラを理解するのに役立つエラー作成のカウンタの例です.
初期複合はStartを呼び出し、0に初期化します.このボタンをクリックすると、コンソール上のcountが変更されましたが、UIは変更されていません.

これは、Composable関数が再配置を実行していないためです.通常、ステータスオブジェクトが変更されると、再配置がトリガーされます.この例で使用するcount変数は、従来のInt変数であるため、前述したように、再配置が実行されていないため、UIは更新されていない.次に、コードを変更して再配置を実行します.
@Composable
fun BadCounter() {
    println("BadCounter: Start")
    var count by mutableStateOf(0)
    println("BadCounter: count initialize : $count")
    Button(
        onClick = {
            println("BadCounter: count onClick (count: $count)")
            count++
            println("BadCounter: count update (count: $count)")
        }
    ) {
        Text("$count")
    }
}
/*
 * BadCounter: Start
 * BadCounter: count initialize : 0
 * BadCounter: count onClick (count: 0)
 * BadCounter: count update (count: 1)
 * BadCounter: Start
 * BadCounter: count initialize : 0
 * BadCounter: count onClick (count: 0)
 * BadCounter: count update (count: 1)
 * BadCounter: Start
 * BadCounter: count initialize : 0
**/ 
ステータスオブジェクトはmutableStateOf関数で定義できます.by Deli Gateを使っていますが、Stateには3つの式があります.
  • val state = mutableStateOf(default)
  • var value by mutableStateOf(default)
  • val (value, setValue) = mutableStateOf(default)
  • 一つ目はstatevalueを変更すると、再配置が起こります.FluthのGetXでobsオブジェクトと似ています.
    2つ目の方法はvalue値を変更することです.varとして発表するのがポイント
    3つ目は反応器のhookに似ています.setValue関数を返します.value値とそのvalueが置き換えられます.
    onClick関数でcount++で値を追加したため、再配置が発生し、ログウィンドウで「BadCounter:Start」を呼び出しました.ただし、実際に実行するとUIは更新されませんが、再コンパイルするたびにcountは0に再初期化され、UIが更新されていないように見えます.コードを完成させます.
    @Composable
    fun Counter() {
        println("Counter: Start")
        var count by remember { mutableStateOf(0) }
        println("Counter: count initialize : $count")
        Button(
            onClick = {
                println("Counter: count onClick (count: $count)")
                count++
                println("Counter: count update (count: $count)")
            }
        ) {
            Text("$count")
        }
    }
    /*
     * Counter: Start
     * Counter: count initialize : 0
     * Counter: count onClick (count: 0)
     * Counter: count update (count: 1)
     * Counter: Start
     * Counter: count initialize : 1
     * Counter: count onClick (count: 1)
     * Counter: count update (count: 2)
     * Counter: Start
     * Counter: count initialize : 2
    **/
    remember関数が表示されます.remember関数を完全に理解するには、必要な内容が多く、次回機会があれば発表します.今は最初の組み合わせの時の変数を覚えて、再組み合わせの時に使えばいいのです.ログを表示すると、count更新後に再配置が発生した場合(起動呼び出し)は0に初期化されず、1に維持されます.@安定性のあるコンセプトと構成可能な関数を作成するときは、次の点に注意してください.
    fun main() = Window {
        MainWindow(rememberMainWindowState())
    }
    
    @Composable
    fun rememberMainWindowState() = remember {
        MainWindowState()
    }
    
    class MainWindowState {
        private val _count = MutableStateFlow(0)
        val count: StateFlow<Int> = _count
    
        fun increase() {
            _count.value++
        }
    }
    
    ウィンドウオブジェクトの状態は非常に複雑である可能性があります.構成可能な関数でこれらをすべて管理するのは非常に困難です.MainWindowStateを定義してウィンドウのステータスを定義し、MainWindow Component関数でステータスを取得することで、メンテナンスやテストが容易なコードを作成できます.
    Compose for DesktopはデスクトップJavaに基づいて駆動されるため、Androidで使用されるLiveDataなどのライブラリは使用できません.幸いなことに、Androidとデスクトップが同じコードを書くことができるように、StateFlowとSharedFlowが追加されました.このオブジェクトをStateオブジェクトに変換する方法CollectAsState()メソッドを使用します.

    State Flowとは?


    AndroidのLiveDataによく似たholderクラス.デフォルトでは、最新の状態(熱的性質)を受信できます.
    LiveDataとの違いは、StateFlowにはデフォルト値が必要であり、AndroidライブラリではなくKotlinライブラリであるため、Androidライフサイクルでの動作はわずかに異なります.後で機会があれば書きます
    残りのコードはスキップされ、UIのサイズやソート方法を設定するように、読み取り方法を理解することができます.
    個人的には,コンパイラが変換コードに関与するフレームワークの学習は難しいと考えられる.しかし、Composeは非常に簡単なライフサイクルであり、他の宣言UIフレームワークに触れたことがある場合は、簡単に適応できる可能性があります.また、AndroidのJetpack Componentは他のJetpackライブラリとの互換性が非常に良いので、非常に期待しています.