Open3

【SwiftUI / Jetpack Compose】ビューのライフサイクルについて調べる

だーら(Flamers / Memotia)だーら(Flamers / Memotia)

親の状態に変化があったとき、親・子のビューはどう変化するか?

SwiftUI

  • 変化する状態自体を保持している親ビューは、再構築されない
  • 子ビューは、変化する状態を参照している・いないにかかわらず再構築される
コード
struct ContentView: View {
    @State private var count = 0

    init() {
        print("ContentView init \(count)")
    }

    var body: some View {
        VStack {
            Text("ContentView: \(count)")
            Button("increment") {
                count += 1
                print("=== ContentView Button Pressed ===")
            }
            Spacer().frame(height: 30)
            ChildCountView(count: count)
            Spacer().frame(height: 30)
            ChildNoCountView()
        }
    }
}

struct ChildCountView: View {
    let count: Int

    init(count: Int) {
        self.count = count
        print("ChildCountView init \(self.count)")
    }

    var body: some View {
        VStack {
            Text("ChildCountView \(count)")
        }
    }
}

struct ChildNoCountView: View {
    init() {
        print("ChildNoCountView init")
    }

    var body: some View {
        VStack {
            Text("ChildNoCountView")
        }
    }
}

Jetpack Compose

  • 状態を保持する親と、状態を参照する子のComposableが再コンポーズされる
  • 状態を参照していない子は再コンポーズされない
コード
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            LifecyclelearningTheme {
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                    ContentView()
                }
            }
        }
    }
}

@Composable
fun ContentView() {
    var count by remember { mutableStateOf(0) }
    println("ContentView() called: $count")

    Column {
        Text(text = "ContentView $count")
        Button(onClick = {
            count++
            println("=== ContentView Button Pressed ===")
        }) {
            Text("increment")
        }
        Spacer(modifier = Modifier.height(30.dp))
        ChildCountView(count)
        Spacer(modifier = Modifier.height(30.dp))
        ChildNoCountView()
    }
}

@Composable
fun ChildCountView(
    count: Int
) {
    println("ChildCountView() called: $count")

    Column {
        Text(text = "ChildCountView $count")
    }
}

@Composable
fun ChildNoCountView() {
    println("ChildNoCountView() called")

    Column {
        Text(text = "ChildNoCountView")
    }
}

だーら(Flamers / Memotia)だーら(Flamers / Memotia)

SwiftUIのViewのidentityについて

Explicit Identity

  • 明示的にViewにidentityを付与し、identityを変更するとViewが再構築される。
コード
struct ContentView: View {
    @State private var id = 1
    init() {
        print("ContentView init")
    }

    var body: some View {
        VStack {
            ChildView()
                .id(id)

            Button("increment id") {
                id += 1
                print("=== increment id ===")
            }
        }
    }
}

struct ChildView: View {
    init() {
        print("ChildView init")
    }

    var body: some View {
        Text("ChildView")
    }
}