Triển khai GUI với Compose, ViewModel và Flow trên Android

Yêu cầu ứng dụng

Thiết kế giao diện gồm 3 ô nhập số và 1 nhãn hiển thị. Nhãn phải cập nhật tổng 3 số theo thời gian thực. Giá trị không hợp lệ trong ô nhập được tính là 0. Giá trị khởi tạo lần lượt là 1, 2, 3.

Khởi tạo dự án

Trong Android Studio: File → New → Project → Chọn Empty Compose Activity → Đặt tên Compose Demo → Hoàn tất thiết lập.

Lớp ViewModel

class SumViewModel : ViewModel() {
    val inputA = MutableStateFlow("1")
    val inputB = MutableStateFlow("2")
    val inputC = MutableStateFlow("3")
    
    val total = combine(inputA, inputB, inputC) { a, b, c ->
        val numA = a.toIntOrNull() ?: 0
        val numB = b.toIntOrNull() ?: 0
        val numC = c.toIntOrNull() ?: 0
        (numA + numB + numC).toString()
    }
}

Thiết lập giao diện

@Composable
fun CalculatorScreen() {
    val viewModel = remember { SumViewModel() }
    
    Column(
        modifier = Modifier.fillMaxSize(),
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center
    ) {
        InputRow(
            value = viewModel.inputA.collectAsState().value,
            onUpdate = { viewModel.inputA.value = it }
        )
        InputRow(
            value = viewModel.inputB.collectAsState().value,
            onUpdate = { viewModel.inputB.value = it }
        )
        InputRow(
            label = "+",
            value = viewModel.inputC.collectAsState().value,
            onUpdate = { viewModel.inputC.value = it }
        )
        ResultRow(total = viewModel.total.collectAsState().value)
    }
}

@Composable
fun InputRow(
    label: String = "",
    value: String,
    onUpdate: (String) -> Unit
) {
    Row(verticalAlignment = Alignment.CenterVertically) {
        Text(
            text = label,
            modifier = Modifier.width(48.dp),
            textAlign = TextAlign.Center
        )
        TextField(
            value = value,
            onValueChange = onUpdate,
            modifier = Modifier.width(180.dp),
            textStyle = LocalTextStyle.copy(textAlign = TextAlign.End)
        )
    }
}

@Composable
fun ResultRow(total: String) {
    Row {
        Text(
            text = "=",
            modifier = Modifier.width(48.dp),
            textAlign = TextAlign.Center
        )
        TextField(
            value = total,
            onValueChange = {},
            readOnly = true,
            modifier = Modifier.width(180.dp),
            textStyle = LocalTextStyle.copy(textAlign = TextAlign.End)
        )
    }
}

Thẻ: Jetpack Compose Android ViewModel Kotlin Flow State Management Compose UI

Đăng vào ngày 10 tháng 6 lúc 01:48