การทำงานกับรูปภาพอาจทำให้เกิดปัญหาด้านประสิทธิภาพได้อย่างรวดเร็วหากคุณไม่ระมัดระวัง
คุณอาจพบข้อผิดพลาด OutOfMemoryError
ได้ง่ายๆ เมื่อทำงาน
กับบิตแมปขนาดใหญ่ ทําตามแนวทางปฏิบัติแนะนําต่อไปนี้เพื่อให้มั่นใจว่าแอปทํางานได้ดีที่สุด
โหลดเฉพาะขนาดของบิตแมปที่คุณต้องการ
สมาร์ทโฟนส่วนใหญ่มีกล้องความละเอียดสูงที่สร้างไฟล์รูปภาพขนาดใหญ่ หากแสดงรูปภาพบนหน้าจอ คุณต้องลดความละเอียดของรูปภาพหรือโหลดรูปภาพให้มีขนาดไม่เกินคอนเทนเนอร์รูปภาพ การโหลดรูปภาพที่มีขนาดใหญ่กว่าที่จำเป็นอย่างต่อเนื่องอาจทำให้แคช GPU หมด ซึ่งส่งผลให้ การแสดงผล UI มีประสิทธิภาพน้อยลง
วิธีจัดการขนาดรูปภาพ
- ลดขนาดไฟล์รูปภาพให้เล็กที่สุด (โดยไม่ส่งผลต่อรูปภาพเอาต์พุต)
- ลองแปลงรูปภาพเป็นรูปแบบ WEBP แทนที่จะเป็น JPEG หรือ PNG
- ระบุรูปภาพขนาดเล็กสำหรับความละเอียดหน้าจอต่างๆ (ดูเคล็ดลับ #3)
- ใช้ไลบรารีการโหลดรูปภาพ ซึ่งจะปรับขนาดรูปภาพให้พอดีกับ ขนาดของมุมมองบนหน้าจอ ซึ่งจะช่วยปรับปรุงประสิทธิภาพการโหลดของหน้าจอได้
ใช้เวกเตอร์แทนบิตแมปหากทำได้
เมื่อแสดงสิ่งใดก็ตามบนหน้าจอ คุณต้องตัดสินใจว่าจะแสดงเป็นเวกเตอร์หรือไม่ ควรใช้ภาพเวกเตอร์แทนบิตแมป เนื่องจากภาพเวกเตอร์จะไม่เป็นพิกเซลเมื่อปรับขนาดให้มีขนาดต่างๆ อย่างไรก็ตาม ไม่ใช่ทุกอย่าง จะแสดงเป็นเวกเตอร์ได้ รูปภาพที่ถ่ายด้วยกล้องจะแปลง เป็นเวกเตอร์ไม่ได้
จัดหาแหล่งข้อมูลสำรองสำหรับขนาดหน้าจอต่างๆ
หากคุณจัดส่งรูปภาพพร้อมกับแอป ให้พิจารณาจัดหาชิ้นงานที่มีขนาดแตกต่างกัน สำหรับความละเอียดของอุปกรณ์ที่แตกต่างกัน ซึ่งจะช่วยลดขนาดการดาวน์โหลด แอปในอุปกรณ์ และปรับปรุงประสิทธิภาพเนื่องจากระบบจะโหลดรูปภาพที่มีความละเอียดต่ำกว่า ในอุปกรณ์ที่มีความละเอียดต่ำกว่า ดูข้อมูลเพิ่มเติมเกี่ยวกับการระบุบิตแมปสำรองสำหรับอุปกรณ์ขนาดต่างๆ ได้ที่เอกสารประกอบเกี่ยวกับบิตแมปสำรอง
เมื่อใช้ ImageBitmap
ให้โทรหา prepareToDraw
ก่อนวาด
เมื่อใช้ ImageBitmap
ให้เรียกใช้ ImageBitmap#prepareToDraw()
ก่อนที่จะวาดจริงเพื่อเริ่มกระบวนการอัปโหลดเท็กซ์เจอร์ไปยัง GPU
ซึ่งจะช่วยให้ GPU เตรียมพื้นผิวและปรับปรุงประสิทธิภาพในการแสดงภาพบนหน้าจอ ไลบรารีการโหลดรูปภาพส่วนใหญ่จะทำการเพิ่มประสิทธิภาพนี้อยู่แล้ว แต่หากคุณทำงานกับคลาส ImageBitmap
ด้วยตนเอง ก็ควรคำนึงถึงเรื่องนี้ไว้
แนะนำให้ส่ง Int
DrawableRes
หรือ URL เป็นพารามิเตอร์ไปยัง Composable แทน Painter
เนื่องจากความซับซ้อนของการจัดการรูปภาพ (เช่น การเขียนฟังก์ชันเท่ากับ
สำหรับ Bitmaps
จะมีค่าใช้จ่ายในการคำนวณสูง) เราจึงไม่ได้ทำเครื่องหมาย API Painter
เป็นคลาสเสถียรอย่างชัดเจน คลาสที่ไม่เสถียรอาจ
ทำให้เกิดการเขียนคอมโพสที่ไม่จำเป็นเนื่องจากคอมไพเลอร์ไม่สามารถอนุมานได้ง่ายๆ ว่า
ข้อมูลมีการเปลี่ยนแปลงหรือไม่
ดังนั้นจึงควรส่ง URL หรือรหัสทรัพยากรที่วาดได้เป็นพารามิเตอร์
ไปยัง Composable แทนการส่ง Painter
เป็นพารามิเตอร์
// Prefer this:
@Composable
fun MyImage(url: String) {
}
// Over this:
@Composable
fun MyImage(painter: Painter) {
}
อย่าจัดเก็บบิตแมปในหน่วยความจำนานเกินความจำเป็น
ยิ่งโหลดบิตแมปลงในหน่วยความจำมากเท่าใด โอกาสที่หน่วยความจำในอุปกรณ์จะหมดก็ยิ่งมากขึ้นเท่านั้น ตัวอย่างเช่น หากโหลดรายการ Image
Composables จำนวนมากบนหน้าจอ ให้ใช้ LazyColumn
หรือ LazyRow
เพื่อให้แน่ใจว่าระบบจะ
เพิ่มพื้นที่ว่างในหน่วยความจำเมื่อเลื่อนรายการขนาดใหญ่
อย่าแพ็กเกจรูปภาพขนาดใหญ่กับไฟล์ AAB/APK
สาเหตุหลักประการหนึ่งที่ทำให้ขนาดการดาวน์โหลดแอปมีขนาดใหญ่คือเนื่องจากกราฟิกที่ รวมอยู่ในไฟล์ AAB หรือ APK ใช้เครื่องมือ APK Analyzer เพื่อให้แน่ใจว่า คุณไม่ได้แพ็กเกจไฟล์ภาพที่มีขนาดใหญ่กว่าที่กำหนด ลดขนาดหรือ พิจารณาจัดเก็บรูปภาพไว้ในเซิร์ฟเวอร์และดาวน์โหลดเฉพาะเมื่อจำเป็น
แนะนำสำหรับคุณ
- หมายเหตุ: ข้อความลิงก์จะแสดงเมื่อ JavaScript ปิดอยู่
- ImageBitmap เทียบกับ ImageVector {:#bitmap-vs-vector}
- บันทึกสถานะ UI ใน Compose
- ระยะต่างๆ ของ Jetpack Compose