Blog
Building CDG Zig's booking flow in Compose
How I moved the booking flow off XML and onto Jetpack Compose, with screen rendering about 30% faster and crash rate down 20%.
ย้าย booking flow ของ CDG Zig มาไว้บน Compose
เดิมที booking flow ของ CDG Zig เขียนด้วย XML layout สิบไฟล์และ stack ของ fragment ทั้งหมด ไม่ว่าจะเป็นการเลือกจุดหมาย เลือกประเภทรถ ยืนยัน ค่าโดยสาร หรือดูคนขับบนแผนที่ — ทุกหน้าเป็นเกาะเล็ก ๆ ของตัวเอง โค้ด UI ซ้ำกันเยอะมาก และหน้าจอที่ผู้ใช้แตะทุกครั้งที่เรียกรถก็ render ช้ากว่าที่ควร
ทำไมถึงย้าย
มีเหตุผลสองข้อ ข้อแรกคือ booking flow เป็นหน้าจอที่ถูกใช้งานมากที่สุดในแอป ข้อที่สองคือหน้าจอใหม่ที่เราอยากเพิ่ม (multi-stop ride, fare estimate) ไม่ สามารถใส่ลงใน layout เก่าได้โดยไม่บังคับให้ XML ขยายออกอย่างเลี่ยงไม่ได้
การเลือก Compose ไม่ได้เพราะ XML ไม่ดี — แต่เพราะ UI ที่ขับเคลื่อน ด้วย state นั้นเข้ากับ booking state ได้เป็นธรรมชาติกว่า เมื่อเราอ่าน หน้าจอได้เป็นฟังก์ชันของ booking object
แก้อะไรไปบ้าง
- แทนที่
Fragmentห้าตัวของ booking flow ด้วยNavHostตัวเดียวและ stack ของหน้าComposable - ดึงชิ้นส่วนที่ใช้ร่วมกัน (date picker, payment row, address card) ออกมาเป็น library เล็ก ๆ ที่ส่วนอื่นของแอปใช้อยู่แล้ว
- ย้ายการโต้ตอบบนแผนที่ออกจาก
MapViewไปยัง Compose interop layer ใหม่ ทำให้ตัด lifecycle glue ที่เคยอยู่ในทุกหน้าออกได้
ตัวเลข
| Metric | ก่อน | หลัง |
|---|---|---|
| Screen render (p95) | 180 ms | 125 ms |
| Crash rate (per 1k) | 0.41 | 0.33 |
| บรรทัดโค้ด UI | 3,200 | 1,840 |
ตัวเลข crash rate คือสิ่งที่ผมใส่ใจที่สุด Compose ไม่ได้แก้ crash ให้หายไป เอง — ทีมเขียน unit และ UI test ที่ขาดอยู่ แล้วเรียง Crashlytics issue ตามลำดับ สิ่งที่ทำให้มันอยู่ได้นานคือนิสัย: ทุกครั้งหลัง release จะเช็ค crash กับ ANR report ทำให้ regression โผล่มาเห็นในไม่กี่วัน ไม่ใช่ใน รีวิวของร้านค้า
ถ้าทำใหม่จะทำต่างไป
จะเริ่มจาก design system ก่อน ไม่ใช่จากหน้าจอ สามสัปดาห์แรกของการย้าย หมดไปกับการสร้างปุ่มและแถวที่มีอยู่แล้วในอีกสองที่ของแอป ถ้าดึงชิ้นส่วนที่ ใช้ร่วมกันออกมาก่อน การย้ายน่าจะเสร็จเร็วขึ้นเกือบครึ่ง