การเพิ่มประสิทธิภาพรูปภาพบิตแมป

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

ใช้ไลบรารีการโหลดรูปภาพ

คุณสามารถปรับปรุงประสิทธิภาพของแอปได้โดยใช้ไลบรารีการโหลดรูปภาพ เช่น Coil (สำหรับโปรเจ็กต์ Kotlin-first) หรือ Glide (สำหรับโปรเจ็กต์ Java) ไลบรารีเหล่านี้จะลดการใช้หน่วยความจำของแอปด้วยการดำเนินการต่างๆ เช่น การแคชรูปภาพ การปรับขนาดกราฟิกเมื่อจำเป็น และการรีไซเคิลออบเจ็กต์กราฟิก

ปรับขนาดรูปภาพเมื่อเหมาะสม

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

ไลบรารีการโหลดรูปภาพ เช่น Coil และ Glide จะจัดการการสุ่มตัวอย่างใหม่นี้ให้คุณโดยอัตโนมัติตามค่าเริ่มต้น คุณสามารถกำหนดค่ากลยุทธ์การลดขนาดตัวอย่างได้โดย ใช้ ImageLoader (สำหรับ Coil) หรือ DownsampleStrategy (สำหรับ Glide)

จัดหาทรัพยากรทางเลือกสำหรับขนาดหน้าจอต่างๆ

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

อย่าใช้ระยะขอบโดยตรง

บางครั้งคุณอาจต้องเพิ่มระยะขอบให้กับรูปภาพ เช่น คุณอาจต้องการให้รูปภาพมีเส้นขอบโปร่งใสล้อมรอบเพื่อทำ Letterbox ในกรณีดังกล่าว อย่า เพิ่มระยะขอบให้กับรูปภาพโดยตรง ซึ่งจะทำให้ขนาดของรูปภาพเปลี่ยนไป แต่ให้คงขนาดของรูปภาพไว้ตามเดิม, และปรับตำแหน่งของรูปภาพบนหน้าจอโดยใช้ InsetDrawable หรือคุณจะเพิ่มระยะขอบลงใน Composable หรือ View ที่เก็บรูปภาพก็ได้

เลือกรูปแบบพิกเซลที่เหมาะสม

สร้างสมดุลระหว่างหน่วยความจำและคุณภาพโดยเลือกรูปแบบพิกเซลที่เหมาะสม ใช้ RGB_565 เมื่อไม่ต้องการความโปร่งใส รูปแบบนี้ใช้หน่วยความจำเพียงครึ่งเดียวของรูปแบบ ARGB_8888 เริ่มต้น

ใน Glide คุณสามารถกำหนดค่านี้ได้โดยใช้ DecodeFormat ใน Coil คุณสามารถ ใช้พร็อพเพอร์ตี้ bitmapConfig

ใช้เวกเตอร์หากทำได้

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

ปล่อยและนำบิตแมปกลับมาใช้ใหม่เมื่อทำได้

ไฟล์กราฟิกขนาดใหญ่อาจใช้หน่วยความจำจำนวนมาก คุณควรปล่อยหรือนำออบเจ็กต์กราฟิกกลับมาใช้ใหม่เมื่อทำได้เพื่อลดผลกระทบ

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

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

เคล็ดลับและเทคนิคอื่นๆ

ส่วนนี้แสดงวิธีอื่นๆ อีก 2-3 วิธีในการปรับปรุงประสิทธิภาพของแอปเมื่อจัดการกราฟิก

อย่าแพ็กเกจรูปภาพขนาดใหญ่ไว้ในไฟล์ AAB/APK

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

ค้นหาบิตแมปที่ซ้ำซ้อน

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

เมื่อใช้ ImageBitmap ให้เรียกใช้ prepareToDraw ก่อนวาด

เมื่อใช้ ImageBitmap ให้เรียกใช้ ImageBitmap#prepareToDraw() ก่อนที่จะวาดจริงเพื่อเริ่มกระบวนการอัปโหลดเท็กซ์เจอร์ไปยัง GPU ซึ่งจะช่วยให้ GPU เตรียมเท็กซ์เจอร์และปรับปรุงประสิทธิภาพในการแสดงภาพบนหน้าจอ ไลบรารีการโหลดรูปภาพส่วนใหญ่จะทำการเพิ่มประสิทธิภาพนี้อยู่แล้ว แต่หากคุณกำลังทำงานกับคลาส ImageBitmap ด้วยตนเอง ก็ควรคำนึงถึงเรื่องนี้ไว้

ควรส่ง Int DrawableRes หรือ URL เป็นพารามิเตอร์ไปยัง Composable แทน Painter

เนื่องจากความซับซ้อนในการจัดการรูปภาพ (เช่น การเขียนฟังก์ชัน equals สำหรับ Bitmaps อาจใช้การคำนวณมาก) API Painter จึงไม่ได้ทำเครื่องหมายว่าเป็น API ที่เสถียรอย่างชัดเจนด้วยคำอธิบายประกอบ @Stable คลาสที่ไม่เสถียรอาจทำให้เกิดการคอมโพสใหม่ที่ไม่จำเป็น เนื่องจากคอมไพเลอร์ไม่สามารถอนุมานได้ง่ายๆ ว่าข้อมูลมีการเปลี่ยนแปลงหรือไม่

ดังนั้น เราขอแนะนำให้ส่ง URL หรือรหัสทรัพยากรที่วาดได้เป็นพารามิเตอร์ไปยัง Composable แทนการส่ง Painter เป็นพารามิเตอร์

// Prefer this:
@Composable
fun MyImage(url: String) {

}
// Over this:
@Composable
fun MyImage(painter: Painter) {

}