ประเด็นสำคัญ
@Composable — คำอธิบายประกอบที่เปลี่ยนฟังก์ชันให้เป็น Composable ฟังก์ชัน Composable เป็นส่วนประกอบของ UI พวกมันไม่ส่งคืน View แต่ส่งองค์ประกอบไปยัง Composition Composition — ต้นไม้ UI ที่สร้างขึ้นจากการเรียกฟังก์ชัน Composable Compose เปรียบเทียบต้นไม้ใหม่กับต้นไม้เก่าและอัปเดตเฉพาะส่วนที่เปลี่ยนแปลง
Recomposition — การเริ่มต้นฟังก์ชัน Composable ใหม่เมื่อสถานะเปลี่ยนแปลง Compose ติดตามว่าสถานะใดถูกอ่านในแต่ละฟังก์ชัน เมื่อสถานะเปลี่ยนแปลง Compose จะเริ่มต้นเฉพาะฟังก์ชันที่อ่านสถานะนั้นใหม่ (Smart Recomposition) Recomposition เป็นแบบมองโลกในแง่ดี: สามารถทำงานหลายครั้งได้ ดังนั้นฟังก์ชันต้องบริสุทธิ์ (ไม่มีผลข้างเคียง) ผลข้างเคียงจะอยู่ใน LaunchedEffect หรือ DisposableEffect ฟังก์ชัน Composable ไม่สามารถเป็น suspend ได้ พวกมันถูกเรียกจากฟังก์ชัน Composable อื่นๆ ลำดับการเรียกไม่ได้รับการรับประกัน (Compose อาจเรียงลำดับใหม่)
// ตัวอย่าง Composable กับ State Hoisting และ LazyColumn
@Composable
fun ItemList(
items: List<String>,
onItemClick: (String) -> Unit
) {
LazyColumn(
modifier = Modifier.fillMaxSize()
) {
items(items) { item ->
Card(
modifier = Modifier
.fillMaxWidth()
.clickable { onItemClick(item) }
.padding(8.dp)
) {
Text(
text = item,
style = MaterialTheme.typography.bodyLarge
)
}
}
}
}
@Composable
fun MainScreen() {
var text by remember { mutableStateOf("") }
val items = listOf("Item 1", "Item 2", "Item 3")
Scaffold(
topBar = {
TopAppBar(title = { Text("Compose App") })
}
) { padding ->
ItemList(
items = items,
onItemClick = { selected -> text = selected }
)
}
}Composition — ต้นไม้แบบประกาศ Recomposition — การเริ่มต้นใหม่อย่างชาญฉลาด IT Sectr แนะนำให้ตรวจสอบความเสถียรของประเภท — ประเภทที่ไม่เสถียรทำให้เกิดการประกอบใหม่มากเกินไป
CompositionLocal — การส่งข้อมูลโดยปริยายใน Compose คล้ายกับ @Environment ใน SwiftUI CompositionLocalProvider — การตั้งค่า current — การอ่าน ใช้สำหรับ: Theme (MaterialTheme), ContentScale, Density CompositionLocal แบบคงที่ — สำหรับการกำหนดค่าไม่มีการเปลี่ยนแปลง CompositionLocal แบบไดนามิก — สำหรับค่าที่เปลี่ยนแปลงได้ (ธีม) IT Sectr แนะนำให้ใช้ CompositionLocal สำหรับการกำหนดค่าทั่วโลกและพารามิเตอร์ที่ชัดเจนสำหรับข้อมูล
remember — รักษาค่าระหว่างการประกอบใหม่ mutableStateOf — สร้างสถานะที่สังเกตได้ (MutableState<T>) เมื่อเปลี่ยนแปลง จะกระตุ้นการประกอบใหม่ State Hoisting — รูปแบบ: สถานะถูกย้ายไปยังคอมโพเนนต์พ่อแม่ ลูกได้รับค่า + การเรียกกลับ State (ไม่เปลี่ยนรูป) — อ่านอย่างเดียว MutableState — อ่าน + เขียน rememberSaveable — คงอยู่ระหว่างการหมุน/การสิ้นสุดกระบวนการ
State Hoisting — หลักการ: state down, events up สถานะถูกเก็บในพ่อแม่และส่งต่อไปยังคอมโพเนนต์ลูกผ่านพารามิเตอร์ คอมโพเนนต์ลูกรายงานการเปลี่ยนแปลงผ่านแลมบ์ดา (การเรียกกลับ) ข้อดี: การนำกลับมาใช้ใหม่ ความสามารถในการทดสอบ แหล่งความจริงเดียว ตัวอย่าง: แทนที่ MyTextField จะเก็บสถานะของตัวเอง พ่อแม่เก็บสตริงและส่งผ่าน value + onValueChange
derivedStateOf — สถานะที่คำนวณ คำนวณใหม่เมื่อการพึ่งพาเปลี่ยนแปลงเท่านั้น ใช้สำหรับการกรอง การแปลง การตรวจสอบ snapshotFlow — แปลง State เป็น Flow ใช้สำหรับห่วงโซ่ปฏิกิริยา collectAsState — รวบรวม Flow เป็น State ภายใน Composable IT Sectr แนะนำ derivedStateOf สำหรับค่าที่คำนวณและ snapshotFlow สำหรับเชื่อมต่อ State กับโครูทีน
Column — เค้าโครงแนวตั้ง (คล้าย LinearLayout แนวตั้ง) Row — เค้าโครงแนวนอน Box — เค้าโครงซ้อน (คล้าย FrameLayout) LazyColumn — รายการแนวตั้งที่เลื่อนได้พร้อมการโหลดแบบขี้เกียจ LazyRow — รายการแนวนอนที่เลื่อนได้ Scaffold — โครงสร้างหลักของหน้าจอ: TopAppBar, BottomBar, FloatingActionButton, Snackbar TopAppBar — แถบด้านบน BottomNavigation — การนำทางด้านล่าง (NavigationBar ใน Material 3) Modifier — ห่วงโซ่: .fillMaxWidth().padding(8.dp).clickable { } ลำดับของตัวปรับแต่งสำคัญ — แต่ละตัวสร้าง wrapper ใหม่
LazyColumn — รายการเสมือน แสดงเฉพาะองค์ประกอบที่มองเห็น การปรับแต่ง: 1) key — คีย์เฉพาะสำหรับ item, 2) contentType — จัดกลุ่ม item ตามประเภท, 3) itemContent — ลดการประกอบใหม่ภายใน item, 4) LazyVerticalGrid / LazyHorizontalGrid — สำหรับกริด LazyLayout — เค้าโครงขี้เกียจแบบกำหนดเอง Paging 3 + Compose — การแบ่งหน้าผ่าน collectAsLazyPagingItems IT Sectr แนะนำ key(item) สำหรับ LazyColumn ทั้งหมดเพื่อการประกอบใหม่ที่คาดเดาได้
Navigation Compose — ไลบรารีการนำทาง NavController — จัดการสแต็กปลายทาง NavHost — คอนเทนเนอร์สำหรับกราฟการนำทาง composable("route") — ลงทะเบียนปลายทาง navController.navigate("route") — นำทาง popBackStack() — กลับไป อาร์กิวเมนต์: composable("detail/{id}", arguments = listOf(navArgument("id") { type = NavType.StringType })) การลิงก์ลึกผ่าน intentFilter BottomNavigation — การรวมกับ NavController: NavBarItem → navigate + popUpTo
แบ็กสแต็กหลายอัน — แบ็กสแต็กแยกสำหรับแต่ละแท็บ BottomNavigation SavedStateHandle — รักษาอาร์กิวเมนต์ระหว่างการสิ้นสุดกระบวนการ NavArgs — อาร์กิวเมนต์ที่ปลอดภัยชนิด (Kotlin 2.0+) ลิงก์ลึก — สคีมา URL สำหรับลิงก์ภายนอก ท่าทางกลับแบบคาดเดา (Android 14+) — รองรับท่าทางกลับพร้อมตัวอย่าง IT Sectr แนะนำให้ใช้ NavArgs เพื่อความปลอดภัยของชนิดและแบ็กสแต็กหลายอันสำหรับ BottomNavigation
LaunchedEffect — เริ่มบล็อก suspend ใน Composition ถูกยกเลิกเมื่อออกจาก Composition เริ่มใหม่เมื่อ keys เปลี่ยนแปลง ใช้สำหรับ: การโหลดข้อมูล ตัวจับเวลา แอนิเมชัน DisposableEffect — สำหรับทรัพยากรที่ต้องการทำความสะอาด: onDispose { } — ยกเลิกการสมัครจาก listener ปิดการเชื่อมต่อ SideEffect — เอฟเฟกต์แบบซิงโครนัส (ทุกการประกอบใหม่) ใช้สำหรับ: การบันทึก การซิงค์กับโค้ดที่ไม่ใช่ Compose IT Sectr แนะนำ LaunchedEffect สำหรับการโหลดข้อมูลและ DisposableEffect สำหรับการทำความสะอาด
| พารามิเตอร์ | Jetpack Compose | SwiftUI |
|---|---|---|
| คำอธิบาย UI | ฟังก์ชัน @Composable + Modifier | View Protocol + @ViewBuilder |
| สถานะ | remember + mutableStateOf | @State, @StateObject |
| การย้ายสถานะ | State Hoisting | @Binding |
| รายการ | LazyColumn | List |
| การนำทาง | NavController + NavHost | NavigationStack (iOS 16+) |
| เอฟเฟกต์ | LaunchedEffect, DisposableEffect | .task{}, .onAppear{} |
| เค้าโครง | Column, Row, Box | VStack, HStack, ZStack |
Compose — ฟังก์ชัน + ตัวปรับแต่ง SwiftUI — struct + ตัวปรับแต่ง แนวคิดคล้ายกัน ไวยากรณ์ต่างกัน IT Sectr แนะนำให้เรียนรู้ทั้งสองเฟรมเวิร์ก — การเข้าใจหนึ่งช่วยให้เรียนรู้อีกหนึ่งง่ายขึ้น
rememberCoroutineScope — การเข้าถึง CoroutineScope นอก LaunchedEffect (เช่น เมื่อคลิกปุ่ม) snapshotFlow — แปลง State เป็น Flow สำหรับห่วงโซ่ produceState — แปลงแหล่งที่ไม่ใช่ Compose เป็น State animateFloatAsState และ animateColorAsState — แอนิเมชันผ่านเอฟเฟกต์ IT Sectr แนะนำ rememberCoroutineScope สำหรับเหตุการณ์ UI และ LaunchedEffect สำหรับการโหลดอัตโนมัติ
MaterialTheme — ธีมส่วนกลางของ Compose สี ลักษณะตัวอักษร รูปร่าง MaterialTheme { } — ห่อหุ้มทั้งแอป Material3 (M3) — ระบบการออกแบบของ Google 2023+ Dynamic Colors — การปรับให้เข้ากับวอลเปเปอร์ (Android 12+) TextStyle — การกำหนดค่าข้อความ: fontSize, fontWeight, lineHeight Shape — การทำให้มุมโค้งมน Elevation — เงา IT Sectr แนะนำ Material3 เป็นค่าเริ่มต้นและ Dynamic Colors สำหรับอุปกรณ์สมัยใหม่
@Composable
fun AppTheme(content: @Composable () -> Unit) {
val colorScheme = if (isSystemInDarkTheme()) {
darkColorScheme(
primary = Color(0xFFBB86FC),
secondary = Color(0xFF03DAC6)
)
} else {
lightColorScheme(
primary = Color(0xFF6200EE),
secondary = Color(0xFF03DAC6)
)
}
MaterialTheme(
colorScheme = colorScheme,
typography = Typography(
bodyLarge = TextStyle(fontSize = 16.sp)
)
) { content() }
}animateFloatAsState — ทำให้ค่า Float เคลื่อนไหว animateColorAsState — ทำให้สีเคลื่อนไหว animateDpAsState — ทำให้ขนาดเคลื่อนไหว AnimatedVisibility — แสดง/ซ่อนด้วย .animateEnterExit() AnimatedContent — แอนิเมชันเมื่อเนื้อหาเปลี่ยน (crossfade, slide) updateTransition — แอนิเมชันตามสถานะ enum Animatable — แอนิเมชันแบบกำหนดเองผ่านอินเทอร์เฟซ Animatable IT Sectr แนะนำ AnimatedVisibility สำหรับรายการและ AnimatedContent สำหรับการเปลี่ยนหน้าจอ
@Composable
fun AnimatedCounter(count: Int) {
val animatedCount by animateFloatAsState(
targetValue = count.toFloat(),
animationSpec = spring(
dampingRatio = Spring.DampingRatioMediumBouncy,
stiffness = Spring.StiffnessLow
)
)
AnimatedContent(targetState = count) { targetCount ->
Text(
text = "$targetCount",
style = MaterialTheme.typography.displayLarge,
modifier = Modifier.animateContentSize()
)
}
}Compose UI Test — การทดสอบหน้าจอ Compose createComposeRule() — กฎ JUnit setContent { } — ตั้งค่า Composable onNodeWithText, onNodeWithTag, onNodeWithContentDescription — ค้นหาองค์ประกอบ performClick, performTextInput, performScrollTo — การกระทำ assertIsDisplayed, assertTextEquals — การยืนยัน Semantics — ต้นไม้ Semantics สำหรับการเข้าถึงและการทดสอบ IdlingResource — รอการดำเนินการแบบอะซิงโครนัส การทดสอบภาพหน้าจอ — Papercuts, Roborazzi IT Sectr แนะนำการทดสอบ UI สำหรับทุกหน้าจอและการทดสอบหน่วยสำหรับ ViewModel
WindowSizeClass — การปรับให้เข้ากับขนาดหน้าจอ (Compact, Medium, Expanded) เกี่ยวข้องกับเค้าโครงที่ปรับเปลี่ยนได้ของ Material3 ใช้ใน Adaptive Navigation Suite สำหรับการสลับอัตโนมัติจาก BottomNavigation เป็น NavigationRail IT Sectr แนะนำ WindowSizeClass สำหรับการปรับ Compose ให้เข้ากับแท็บเล็ตและเดสก์ท็อป
Paging 3 + Compose — ไลบรารีการแบ่งหน้าจาก Google PagingData — สตรีมหน้า PagingConfig — การตั้งค่า (pageSize, prefetchDistance) collectAsLazyPagingItems() — รวบรวมใน Compose PagingSource — แหล่งที่มาแบบกำหนดเอง RemoteMediator — การโหลดแบบผสม (เครือข่าย + DB) Paging 3 เป็นมาตรฐานสำหรับรายการเลื่อนไม่สิ้นสุดใน Compose
คำถามที่พบบ่อย
@Composable — คำอธิบายประกอบสำหรับฟังก์ชัน UI การเรียกฟังก์ชัน Composable สร้าง Composition Recomposition — การเริ่มต้นใหม่เมื่อสถานะเปลี่ยนแปลง
State Hoisting — การย้ายสถานะขึ้นไปยังพ่อแม่ State down, events up คอมโพเนนต์ที่นำกลับมาใช้ใหม่และทดสอบได้
Recomposition — การเริ่มต้นฟังก์ชัน Composable ใหม่เมื่อสถานะเปลี่ยนแปลง Smart Recomposition — ชุดฟังก์ชันขั้นต่ำ
NavController — สแต็กปลายทาง NavHost — คอนเทนเนอร์กราฟ composable("route") — การลงทะเบียน navigate() — การเปลี่ยน
LaunchedEffect — บล็อก suspend ที่ยกเลิกอัตโนมัติ DisposableEffect — ทรัพยากรที่มีการทำความสะอาด onDispose
สรุป
เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ