0Pricing
Android Academy · บทเรียน

การจัดการสถานะแบบฟอร์ม

เก็บและอัปเดตค่าฟิลด์ด้วยสถานะ

การจัดการสถานะแบบฟอร์ม เป็นบทเรียน Android Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Android Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Android Academy มีบทเรียนทั้งหมด 4 บทเรียน

จากช่องเดียวสู่แบบฟอร์ม

ช่องข้อความเดียวจัดการได้ง่าย แต่แบบฟอร์มจริงมีหลายช่อง เช่น ชื่อ อีเมล รหัสผ่าน และอาจมีช่องทำเครื่องหมายด้วย ในบทเรียนนี้ คุณจะได้เรียนรู้วิธีที่เป็นระเบียบในการเก็บและอัปเดตสถานะของแบบฟอร์มทั้งชุดใน Jetpack Compose

หากทำความเข้าใจส่วนนี้ได้ถูกต้อง การตรวจสอบความถูกต้อง การส่งข้อมูล และการแสดงตัวอย่างจะกลายเป็นเรื่องง่าย

สถานะแยกอิสระหลายรายการ

แนวทางที่ง่ายที่สุดคือใช้ mutableStateOf หนึ่งรายการต่อหนึ่งช่อง แต่ละช่องจะอ่านและอัปเดตสถานะส่วนของตัวเอง

แนวทางนี้เหมาะสมอย่างยิ่งสำหรับแบบฟอร์มขนาดเล็กที่มีสองหรือสามช่อง

@Composable
fun LoginForm() {
    var email by remember { mutableStateOf("") }
    var password by remember { mutableStateOf("") }

    Column {
        OutlinedTextField(email, { email = it }, label = { Text("Email") })
        OutlinedTextField(password, { password = it }, label = { Text("Password") })
    }
}

การจัดกลุ่มสถานะในคลาสข้อมูล

เมื่อแบบฟอร์มใหญ่ขึ้น การมีตัวแปรแยกกันจำนวนมากจะยุ่งยาก ทางเลือกที่เป็นระเบียบกว่าคือจำลองแบบฟอร์มทั้งชุดเป็น data class ที่เปลี่ยนแปลงไม่ได้

คุณเก็บสถานะเพียงส่วนเดียวที่ถือออบเจ็กต์นั้นไว้ แล้วอัปเดตด้วย copy()

data class SignUpState(
    val name: String = "",
    val email: String = "",
    val agreedToTerms: Boolean = false
)

การอัปเดตด้วย copy()

เนื่องจากออบเจ็กต์สถานะเปลี่ยนแปลงไม่ได้ คุณจึงไม่แก้ไขออบเจ็กต์เดิมโดยตรง แต่สร้างสำเนาใหม่ที่เปลี่ยนค่าหนึ่งช่อง แล้วกำหนดกลับเข้าไป

วิธีนี้ทำให้โมเดลสถานะของ Compose คาดเดาได้: ออบเจ็กต์ใหม่หมายถึงภาพสถานะใหม่ ซึ่งจะเรียกการจัดองค์ประกอบใหม่

var form by remember { mutableStateOf(SignUpState()) }

OutlinedTextField(
    value = form.name,
    onValueChange = { form = form.copy(name = it) },
    label = { Text("Name") }
)

ฟอร์ม Data Class แบบครบถ้วน

ในที่นี้ ฟอร์มทั้งหมดขับเคลื่อนด้วย SignUpState เพียงหนึ่งรายการ แต่ละฟิลด์จะอัปเดตพร็อพเพอร์ตี้เดียวผ่าน copy()

สังเกตว่าการอ่านค่าทั้งหมดของฟอร์มในเวลาใดก็ตามทำได้ง่ายเพียงใด: ใช้แค่ form เท่านั้น

var form by remember { mutableStateOf(SignUpState()) }

Column {
    OutlinedTextField(
        value = form.name,
        onValueChange = { form = form.copy(name = it) },
        label = { Text("Name") }
    )
    OutlinedTextField(
        value = form.email,
        onValueChange = { form = form.copy(email = it) },
        label = { Text("Email") }
    )
}

ช่องทำเครื่องหมายและสวิตช์

อินพุตไม่ได้มีแค่ข้อความเท่านั้น Checkbox หรือ Switch ก็ทำงานในลักษณะเดียวกัน นั่นคือใช้ค่าบูลีนร่วมกับคอลแบ็ก onCheckedChange

จัดเก็บค่าบูลีนไว้ในสถานะของฟอร์มเช่นเดียวกับสตริง

var form by remember { mutableStateOf(SignUpState()) }

Row(verticalAlignment = Alignment.CenterVertically) {
    Checkbox(
        checked = form.agreedToTerms,
        onCheckedChange = { form = form.copy(agreedToTerms = it) }
    )
    Text("I agree to the terms")
}

การคำนวณค่าจากสถานะ

ประโยชน์สำคัญอย่างหนึ่งของสถานะที่มีแหล่งข้อมูลเดียวคือ คุณสามารถคำนวณสิ่งต่าง ๆ จากสถานะได้โดยไม่ต้องจัดเก็บตัวแปรเพิ่มเติม ตัวอย่างเช่น ฟอร์มพร้อมส่งหรือไม่

ใช้ derivedStateOf (หรือนิพจน์อย่างง่าย) เพื่อให้ผลลัพธ์อัปเดตโดยอัตโนมัติเมื่อฟอร์มเปลี่ยนแปลง

var form by remember { mutableStateOf(SignUpState()) }

val canSubmit by remember {
    derivedStateOf {
        form.name.isNotBlank() &&
        form.email.isNotBlank() &&
        form.agreedToTerms
    }
}

Button(onClick = { /* submit */ }, enabled = canSubmit) {
    Text("Sign Up")
}

การคงอยู่เมื่อการกำหนดค่าเปลี่ยนแปลง

remember จะเก็บสถานะไว้ระหว่างการจัดองค์ประกอบใหม่ แต่สถานะจะหายไปเมื่อเกิดการเปลี่ยนแปลงการกำหนดค่า เช่น การหมุนหน้าจอ หากต้องการเก็บค่าพื้นฐานไว้ระหว่างการหมุนหน้าจอ ให้ใช้ rememberSaveable

ใช้งานได้ทันทีสำหรับชนิดข้อมูลพื้นฐานและชนิด Parcelable

var email by rememberSaveable { mutableStateOf("") }

OutlinedTextField(
    value = email,
    onValueChange = { email = it },
    label = { Text("Email") }
)

ยกสถานะของฟอร์มไปไว้ใน ViewModel

สำหรับฟอร์มที่ซับซ้อนกว่าฟอร์มพื้นฐาน ให้เก็บสถานะไว้ใน ViewModel สถานะจะคงอยู่เมื่อการกำหนดค่าเปลี่ยนแปลง และช่วยแยกตรรกะของส่วนติดต่อผู้ใช้ออกจาก composable

composable จะอ่านสถานะและส่งต่อเหตุการณ์ ส่วน ViewModel เป็นเจ้าของข้อมูลที่ถูกต้อง

class SignUpViewModel : ViewModel() {
    var state by mutableStateOf(SignUpState())
        private set

    fun onNameChange(value: String) {
        state = state.copy(name = value)
    }
}

การเชื่อมต่อ ViewModel

ภายใน composable ให้เรียกใช้ ViewModel และผูกแต่ละฟิลด์เข้ากับสถานะและตัวจัดการของฟิลด์นั้น ส่วนติดต่อผู้ใช้จึงมีโค้ดน้อยและทดสอบได้

นี่คือโครงสร้างที่แนะนำสำหรับฟอร์มในแอปจริง

@Composable
fun SignUpScreen(vm: SignUpViewModel = viewModel()) {
    OutlinedTextField(
        value = vm.state.name,
        onValueChange = vm::onNameChange,
        label = { Text("Name") }
    )
}

Kotlin ล้วน: การใช้งาน copy()

รูปแบบการอัปเดตด้วย copy() เป็นพฤติกรรมมาตรฐานของ data class ใน Kotlin ในตัวอย่างนี้ โค้ดทำงานแยกเป็นอิสระ เพื่อให้เห็นว่าการอัปเดตแต่ละครั้งสร้างออบเจ็กต์ใหม่ขึ้นมา

data class SignUpState(
    val name: String = "",
    val email: String = ""
)

fun main() {
    var state = SignUpState()
    state = state.copy(name = "Ada")
    state = state.copy(email = "ada@dev.io")
    println(state)
}

ตรวจสอบความเข้าใจ

คุณสร้างแบบจำลองฟอร์มเป็น data class ที่เปลี่ยนแปลงไม่ได้และเก็บไว้ในสถานะ คุณควรอัปเดตฟิลด์เดียวอย่างไร

สรุปทบทวน

คุณได้เรียนรู้วิธีจัดการสถานะสำหรับฟอร์มทั้งชุดแล้ว:

  • ฟอร์มขนาดเล็ก: ใช้ mutableStateOf หนึ่งรายการต่อหนึ่งฟิลด์
  • ฟอร์มขนาดใหญ่: ใช้ data class เดียวที่เปลี่ยนแปลงไม่ได้ และอัปเดตด้วย copy()
  • ค่าบูลีนขับเคลื่อน Checkbox และ Switch ในลักษณะเดียวกับที่ข้อความขับเคลื่อนฟิลด์ต่าง ๆ
  • คำนวณค่าอย่าง "ส่งได้หรือไม่" แทนการจัดเก็บค่าเหล่านั้น
  • ใช้ rememberSaveable สำหรับการหมุนหน้าจอ และใช้ ViewModel สำหรับหน้าจอจริง

ถัดไป: การตรวจสอบอินพุตและการแสดงข้อผิดพลาดที่ช่วยให้ผู้ใช้แก้ไขได้

คำถามที่พบบ่อย

บทเรียน “การจัดการสถานะแบบฟอร์ม” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “การจัดการสถานะแบบฟอร์ม” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Android Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Android Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “การจัดการสถานะแบบฟอร์ม”

เก็บและอัปเดตค่าฟิลด์ด้วยสถานะ คุณปฏิบัติ Android Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Android Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Android Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน

บทเรียน “การจัดการสถานะแบบฟอร์ม” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Android Academy นี้ได้ไหม

ได้ บทเรียน Android Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. TextField และข้อมูลนำเข้าจากผู้ใช้
  2. การจัดการสถานะแบบฟอร์ม
  3. การตรวจสอบข้อมูลนำเข้า
  4. ตัวเลือกและการทำงานของแป้นพิมพ์
← กลับไปที่ Android Academy