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