แม้ว่าประสิทธิภาพของแอปมักจะเทียบเท่ากับ UI ที่ราบรื่นและเวลาเริ่มต้นที่รวดเร็ว แต่หน่วยความจำก็เป็นรากฐานที่เงียบซึ่งเมตริกที่มองเห็นได้เหล่านี้สร้างขึ้น เราเห็นการเปลี่ยนแปลงที่หน่วยความจำของอุปกรณ์มีความสำคัญมากกว่าที่เคย เราไม่เพียงแต่ก้าวหน้าในการเพิ่มประสิทธิภาพหน่วยความจำของ Android ด้วย Android 17 แต่ยังให้การสนับสนุนเครื่องมือและ API เพื่อช่วยให้คุณพร้อมรับมือกับข้อกำหนดด้านหน่วยความจำที่เข้มงวดมากขึ้นในช่วงปลายปีนี้
ตั้งแต่ Android 17 เป็นต้นไป ระบบจะเริ่มบังคับใช้ขีดจำกัดหน่วยความจำของแอปตาม RAM ทั้งหมดของอุปกรณ์ เพื่อให้มั่นใจถึงความเสถียรของอุปกรณ์ หากแอปเกินขีดจำกัดเหล่านั้น Android จะหยุดกระบวนการโดยไม่มีสแต็กเทรซที่เกี่ยวข้อง
นอกเหนือจากการสิ้นสุดการทำงานโดยบังคับเหล่านี้แล้ว การใช้งานหน่วยความจำที่ไม่ได้เพิ่มประสิทธิภาพจะทำให้ประสบการณ์ของผู้ใช้แย่ลงอย่างหลีกเลี่ยงไม่ได้ เมื่อแอปใกล้ถึงขีดจำกัดของหน่วยความจำฮีป ระบบจะเรียกใช้ระบบจัดการหน่วยความจำที่ไม่ใช้แล้วบ่อยครั้ง ซึ่งทำให้ UI สะดุดอย่างเห็นได้ชัด นอกจากนี้ เมื่ออุปกรณ์มีหน่วยความจำไม่เพียงพอ ระบบจะพยายามกู้คืนหน้าเว็บ ซึ่งทำให้ CPU ทำงานหนักเกินไป, UI ทำงานช้า และแบตเตอรี่หมดเร็ว หากหน่วยความจำไม่เพียงพออย่างรุนแรง อาจทำให้เกิดเหตุการณ์ Low Memory Killer (LMK) ซึ่งจะสิ้นสุดกระบวนการทำงานเบื้องหลังอย่างกะทันหัน และบังคับให้แอปมี Cold Start ที่ช้าและสูญเสียสถานะของผู้ใช้
เราขอแนะนำให้คุณใช้กลยุทธ์การเพิ่มประสิทธิภาพหน่วยความจำต่อไปนี้เพื่อสร้างแอปที่มีประสิทธิภาพสูงและหลีกเลี่ยงการสิ้นสุดการทำงานโดยบังคับ
- เพิ่มประสิทธิภาพไบต์โค้ดให้สูงสุดด้วย R8
- เพิ่มประสิทธิภาพการโหลดรูปภาพ
- ตรวจหาและแก้ไขหน่วยความจำรั่วด้วย Android Studio
- ตัดหน่วยความจำเมื่อแอปออกจากสถานะที่มองเห็นได้
- การสังเกตการณ์หน่วยความจำขั้นสูงด้วย ProfilingManager
นอกจากนี้ เรายังมีบล็อกโพสต์ฉบับย่อในรูปแบบวิดีโอด้วย อย่าลืมไปดูกันนะ
ทำความเข้าใจการจำกัดการใช้หน่วยความจำของแอปใน Android 17
Android 17 มีการจำกัดหน่วยความจำของแอปเพื่อป้องกันไม่ให้ "ผู้ไม่ประสงค์ดีเพียงคนเดียว" ทำลายประสบการณ์การทำงานแบบมัลติทาสก์และความเสถียรของอุปกรณ์ทั้งหมดของผู้ใช้
รายละเอียดเหตุผลที่ทำให้เกิดการเปลี่ยนแปลงสถาปัตยกรรมนี้มีดังนี้
- ป้องกันการปิดแอปแบบต่อเนื่อง: เมื่อแอปมีขนาดใหญ่เกินไปหรือหน่วยความจำรั่วไหลขณะอยู่ในสถานะที่มีสิทธิ์ (เช่น กำลังเรียกใช้บริการที่ทำงานอยู่เบื้องหน้า) ระบบจะป้องกันไม่ให้ Low Memory Killer (LMK) ของระบบปิดแอปในตอนแรก เมื่อแอปเดียวนี้เติบโตขึ้นโดยไม่มีการตรวจสอบและกักตุน RAM ไว้ LMK จึงต้องชดเชยด้วยการปิดแอปที่แคชไว้และงานที่ทำงานอยู่เบื้องหลังขนาดเล็กอื่นๆ อีกหลายสิบรายการที่ทำงานได้ดีเพื่อเรียกคืนพื้นที่สำหรับแอปที่ใช้หน่วยความจำมาก
- การรักษาสถานะมัลติทาสก์และสถานะของผู้ใช้: เมื่อระบบถูกบังคับให้ล้างแอปที่แคชไว้เพื่อรองรับกระบวนการเดียวที่รั่วไหล ประสบการณ์มัลติทาสก์จะลดลงอย่างมาก ผู้ใช้ที่กลับมาใช้แอปพลิเคชันที่แคชไว้ก่อนหน้านี้จะพบว่า Cold Start ทำงานช้าลงแทนที่จะเป็นการกลับมาทำงานต่อแบบ Warm Start ที่รวดเร็ว ความไม่มีประสิทธิภาพนี้ทำให้ CPU ทำงานหนักขึ้นและแบตเตอรี่หมดเร็วขึ้น นอกจากนี้ยังอาจทำลายบริบทของผู้ใช้ในแอปที่ใช้ล่าสุด เช่น ตำแหน่งการเลื่อน สแต็กการนำทาง และความคืบหน้าในเกม
หากต้องการดูว่าเซสชันแอปได้รับผลกระทบจากข้อจำกัดเหล่านี้ในฟิลด์หรือไม่ คุณสามารถเรียก getDescription() ภายใน ApplicationExitInfo หากระบบใช้ขีดจำกัด ระบบจะรายงานเหตุผลที่ออกเป็น REASON_OTHER และสตริงคำอธิบายจะมี "MemoryLimiter:AnonSwap" นอกจากนี้ คุณยังใช้ประโยชน์จากการสร้างโปรไฟล์ตามทริกเกอร์โดยใช้ TRIGGER_TYPE_ANOMALY เพื่อบันทึกฮีปดัมป์โดยอัตโนมัติเมื่อถึงขีดจำกัดหน่วยความจำได้ด้วย นอกจากนี้ Android ยังทำงานอย่างต่อเนื่องเพื่อแสดงเมตริกหน่วยความจำในฟิลด์เพิ่มเติมแก่นักพัฒนาแอปภายใน Google Play Console
นอกจากนี้ เรายังได้ขยายเอกสารประกอบเกี่ยวกับขีดจำกัดของหน่วยความจำให้ครอบคลุมคำสั่งการแก้ไขข้อบกพร่องในเครื่อง ซึ่งช่วยให้คุณจำลองข้อจำกัดด้านหน่วยความจำในสภาพแวดล้อมในเครื่องและตรวจสอบลักษณะการทำงานของแอปพลิเคชันภายใต้การบังคับใช้ขีดจำกัดของหน่วยความจำได้
เพิ่มประสิทธิภาพไบต์โค้ดให้สูงสุดด้วย R8
วิธีที่มีประสิทธิภาพสูงในการลดหน่วยความจำที่ใช้ของแอปคือการเปิดใช้เครื่องมือเพิ่มประสิทธิภาพ R8 การย่อคลาส เมธอด และฟิลด์ให้มีชื่อสั้นลง รวมถึงการนำโค้ดและทรัพยากรที่ไม่ได้ใช้ออกจะช่วยให้ R8 ลดการใช้หน่วยความจำของแอปได้อย่างมากด้วยการลดจำนวนโค้ดที่ต้องใช้ในระหว่างการดำเนินการ
R8 จะลดโค้ดที่อยู่ในหน่วยความจำ ซึ่งจะช่วยลดการใช้หน่วยความจำและลดความเสี่ยงในการสิ้นสุด LMK ซึ่งจะส่งผลให้เกิด Warm Start บ่อยขึ้นแทนที่จะเป็น Cold Start ช้า นอกจากนี้ ไบต์โค้ดที่ได้รับการเพิ่มประสิทธิภาพยังช่วยลดค่าใช้จ่ายของ CPU ในเทรดหลัก ซึ่งจะช่วยลดอัตรา ANR โดยตรงเพื่อให้ผู้ใช้ได้รับประสบการณ์ที่ราบรื่นยิ่งขึ้น ตัวอย่างเช่น ธนาคารดิจิทัล Monzo เปิดใช้การเพิ่มประสิทธิภาพ R8 แบบเต็มและพบว่าอัตรา ANR ลดลง 35%, อัตรา Cold Start ดีขึ้น 30% และขนาดแอปโดยรวมลดลง 9%
วิธีกำหนดค่า R8 ในไฟล์ build.gradle อย่างถูกต้อง
- ตั้งค่า
isShrinkResources = trueและisMinifyEnabled = true - ใช้
proguard-android-optimize.txtแทนproguard-android.txtแบบเดิม ซึ่งจะป้องกันการเพิ่มประสิทธิภาพและไม่รองรับในปลั๊กอิน Android Gradle 9 อีกต่อไป - นำ
android.enableR8.fullMode = falseออกจากgradle.properties
หากคุณใช้การสะท้อนในฐานของโค้ด ให้เพิ่มกฎ Keep เพื่อป้องกันไม่ให้ R8 เพิ่มประสิทธิภาพโค้ดส่วนดังกล่าว อย่าลืมกำหนดขอบเขตของกฎการเก็บรักษาให้แคบลงเพื่อเพิ่มประสิทธิภาพสูงสุด
หากต้องการเพิ่มประสิทธิภาพสูงสุด โปรดทําตามแนวทางปฏิบัติแนะนําต่อไปนี้ในไฟล์กฎการเก็บ
- นำตัวเลือกส่วนกลาง เช่น
-dontoptimize,-dontshrinkและ-dontobfuscateที่ป้องกันไม่ให้ R8 เพิ่มประสิทธิภาพฐานของโค้ดทั้งหมดออก - นำกฎการเก็บที่ป้องกันการเพิ่มประสิทธิภาพคอมโพเนนต์ Android เช่น กิจกรรม บริการ มุมมอง หรือตัวรับสัญญาณออกอากาศออก
- ปรับแต่งกฎการเก็บรักษาแบบกว้างของทั้งแพ็กเกจเพื่อกำหนดเป้าหมายเฉพาะคลาสหรือเมธอดที่ต้องการ
ดูแนวทางปฏิบัติแนะนำเพิ่มเติมได้ในเอกสารประกอบเกี่ยวกับกฎการเก็บ
แนวทางปฏิบัติแนะนำสำหรับนักพัฒนาแอปไลบรารี R8
หากคุณเป็นนักพัฒนาไลบรารี ให้วางกฎที่ผู้บริโภคต้องการไว้ใน consumer-rules file อย่างเคร่งครัด และเก็บกฎการป้องกันภายในของไลบรารีไว้ในไฟล์ proguard-rules.pro ดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีเพิ่มประสิทธิภาพไลบรารีได้ที่การเพิ่มประสิทธิภาพสำหรับผู้เขียนไลบรารี
ตัววิเคราะห์การกำหนดค่า R8
หากต้องการตรวจสอบการเพิ่มประสิทธิภาพ R8 ให้ใช้เครื่องมือวิเคราะห์การกำหนดค่า เครื่องมือวิเคราะห์การกำหนดค่าจะแสดงสถานะปัจจุบันของการเพิ่มประสิทธิภาพพร้อม คะแนนการปรับให้ยากต่อการอ่าน การเพิ่มประสิทธิภาพ และการลดขนาด นอกจากนี้ เครื่องมือวิเคราะห์การกำหนดค่ายังช่วยให้คุณทราบจำนวนคลาส เมธอด หรือฟิลด์ที่กฎ Keep แต่ละรายการป้องกันไม่ให้มีการเพิ่มประสิทธิภาพได้ด้วย ปรับแต่งกฎการเก็บรักษาแบบกว้างระดับแพ็กเกจเหล่านี้เพื่อปลดล็อกการเพิ่มประสิทธิภาพสูงสุด
การใช้เครื่องมือวิเคราะห์การกำหนดค่าจะช่วยให้คุณระบุกฎการเก็บที่ครอบคลุมกฎการเก็บอื่นๆ กฎการเก็บที่ซ้ำซ้อน และกฎการเก็บที่ไม่ได้ใช้ได้ด้วย
ทักษะของตัวแทน R8
นอกจากนี้ คุณยังใช้ประโยชน์จากทักษะของ R8 Agent กับเอเจนต์ Android Studio หรือเครื่องมือ AI อื่นๆ เพื่อแก้ไขการกำหนดค่าที่ไม่ถูกต้องและปรับแต่งกฎเพื่อปรับปรุงประสิทธิภาพของแอปได้ด้วย (ข้อมูลเชิงลึกจากทักษะที่ทำงานด้วยระบบ AI จะต้องมีการยืนยันทางเทคนิค)
เพิ่มประสิทธิภาพการโหลดรูปภาพ
โดยปกติแล้ว บิตแมปจะเป็นออบเจ็กต์ทั่วไปที่ใหญ่ที่สุดซึ่งอยู่ในหน่วยความจำของแอป ซึ่งแสดงถึงขั้นตอนสุดท้ายของกระบวนการโหลดรูปภาพที่ไฟล์ที่บีบอัด เช่น JPEG หรือ PNG จะได้รับการถอดรหัสเป็นข้อมูลพิกเซลดิบเพื่อแสดง ซึ่งหมายความว่ารูปภาพที่บีบอัดขนาด 100 KB อาจขยายเป็น RAM หลายเมกะไบต์ได้ เนื่องจากระบบจะกำหนดการใช้หน่วยความจำตามขนาดพิกเซลและความลึกของสีของรูปภาพ เนื่องจากการดำเนินการบิตแมปมักอยู่ในเส้นทางวิกฤตในการวาดเฟรม รูปภาพที่ไม่ได้เพิ่มประสิทธิภาพจึงทำให้หน่วยความจำบวมอย่างรุนแรงและ UI กระตุก
Google ขอแนะนำให้ใช้ประโยชน์จากไลบรารีการโหลดรูปภาพ Coil สำหรับโปรเจ็กต์ที่ใช้ Kotlin เป็นหลัก โดยเฉพาะอย่างยิ่งเมื่อพัฒนาด้วย Jetpack Compose และ Glide สำหรับแอปพลิเคชันที่ใช้ Java
ใช้แนวทางปฏิบัติแนะนำ 5 ข้อต่อไปนี้
- ลดขนาดความละเอียดของรูปภาพ: หากโหลดบิตแมปด้วยตนเอง ให้หลีกเลี่ยงการโหลดรูปภาพขนาดใหญ่ลงในมุมมองภาพขนาดย่อขนาดเล็ก ใช้ inSampleSize เพื่อโหลดเวอร์ชันที่เล็กกว่า Glide และ Coil จะลดขนาดรูปภาพโดยค่าเริ่มต้น และคุณสามารถกำหนดค่ากลยุทธ์การลดขนาดนี้ได้โดยใช้ DownsampleStrategy และ ImageLoader ตามลำดับ
- การครอบตัด: หลีกเลี่ยงการฝังระยะขอบลงในไฟล์รูปภาพโดยตรงเพื่อวัตถุประสงค์ในการสร้างแถบดำบนและล่าง (เช่น การสร้างเส้นขอบโปร่งใสเพื่อขยายขนาดรูปภาพ) แทนที่จะฝังขอบเหล่านี้ ให้ใช้ InsetDrawable หรือใช้ระยะห่างจากขอบโดยตรงภายใน View หรือ Composable ที่มีบิตแมป
- กำหนดค่า: ปรับสมดุลหน่วยความจำและคุณภาพโดยเลือกรูปแบบพิกเซลที่เหมาะสม ใช้
RGB_565เมื่อไม่จำเป็นต้องใช้ความโปร่งใส ซึ่งใช้หน่วยความจำเพียงครึ่งหนึ่งของรูปแบบARGB_8888เริ่มต้น ใน Glide คุณสามารถกำหนดค่านี้ได้โดยใช้พร็อพเพอร์ตี้ DecodeFormat และใน Coil คุณสามารถใช้พร็อพเพอร์ตี้ bitmapConfig ได้ - จัดลำดับความสำคัญของ Vector Drawable: สำหรับชิ้นงานเรขาคณิตพื้นฐาน ให้ใช้ ShapeDrawable เป็นทางเลือกที่มีขนาดเล็กแทนการถอดรหัสบิตแมปแบบแรสเตอร์ การกำหนดชิ้นงานเหล่านี้เพียงครั้งเดียวผ่าน XML จะช่วยให้มั่นใจได้ว่าชิ้นงานจะปรับขนาดได้อย่างราบรื่นในความหนาแน่นของจอแสดงผลทั้งหมด พร้อมทั้งช่วยลดการใช้หน่วยความจำที่เกิดจากทรัพยากรได้อย่างมีประสิทธิภาพ
- การนำกลับมาใช้ใหม่: หากแอปพลิเคชันจัดการบิตแมปด้วยตนเอง เมื่อไม่จำเป็นต้องใช้บิตแมปแล้ว แอปควรเรียกใช้
bitmap.recycle()และทิ้งการอ้างอิงBitmapทันทีเพื่อลดการเสียหน่วยความจำ หากใช้ไลบรารีการโหลดรูปภาพ เช่น Glide หรือ Coil ให้ส่งคืนบิตแมปไปยังพูลที่มีการจัดการของไลบรารี การจัดสรรบัฟเฟอร์ที่มีอยู่สำหรับความต้องการหน่วยความจำในอนาคตจะช่วยให้พูลหลีกเลี่ยงค่าใช้จ่ายในการจัดสรรใหม่ได้อย่างมีประสิทธิภาพ
ดูข้อมูลเพิ่มเติมได้ในเอกสารประกอบเกี่ยวกับการเพิ่มประสิทธิภาพรูปภาพ
เครื่องมือ Android Studio
นอกจากนี้ คุณยังกำจัดบิตแมปที่ซ้ำกันได้โดยใช้ Android Studio Narwhal 4 วิธีค้นหาไฟล์ที่ซ่อนมีดังนี้
- เปิดแท็บ Profiler ใน Android Studio
- คลิก Heap Dump (หรือ "วิเคราะห์การใช้หน่วยความจำ") แล้วกดบันทึกเพื่อถ่ายภาพรวมสถานะหน่วยความจำปัจจุบันของแอป
- สแกนผลการวิเคราะห์เพื่อหาสามเหลี่ยมคำเตือนสีเหลือง ⚠️ ซึ่ง Android Studio ใช้เพื่อแจ้งว่ามีการจัดเก็บบิตแมปที่ซ้ำกันหลายครั้ง หรือไปที่ส่วนหัวของโปรไฟล์เลอร์ เลือก "กรองตาม:" แล้วเลือกการตั้งค่า "บิตแมปที่ซ้ำกัน"
- คลิกรายการที่ถูกแจ้งเพื่อเปิดแผงตัวอย่างบิตแมป ซึ่งจะช่วยให้คุณเห็นภาพที่ทำผิดซ้ำได้อย่างชัดเจน
- ใช้การยืนยันด้วยภาพดังกล่าวเพื่อติดตามตรรกะการโหลดที่ซ้ำซ้อนในโค้ด และใช้กลยุทธ์การแคชที่ดีขึ้น
ตรวจหาและแก้ไขหน่วยความจำรั่วด้วย Android Studio
หน่วยความจำรั่วใน Android เกิดขึ้นเมื่อโค้ดเก็บการอ้างอิงของออบเจ็กต์ไว้นานหลังจากวงจรของออบเจ็กต์สิ้นสุดลง ซึ่งจะป้องกันไม่ให้ตัวเก็บขยะ (GC) เรียกคืนหน่วยความจำดังกล่าว ซึ่งในที่สุดจะทำให้ประสิทธิภาพการทำงานช้าลงหรือเกิดข้อผิดพลาด OutOfMemoryError (OOM)
Android Studio Panda 3 มีงานโปรไฟล์ LeakCanary โดยเฉพาะ ซึ่งช่วยให้นักพัฒนาแอปวิเคราะห์หน่วยความจำรั่วแบบเรียลไทม์และแมปการติดตามได้โดยตรงภายใน IDE
งาน Profiler ของ LeakCanary ใน Android Studio จะย้ายการวิเคราะห์หน่วยความจำรั่วไหลจากอุปกรณ์ไปยังคอมพิวเตอร์สำหรับการพัฒนาซอฟต์แวร์อย่างต่อเนื่อง ซึ่งจะช่วยเพิ่มประสิทธิภาพอย่างมากในระยะการวิเคราะห์การรั่วไหลเมื่อเทียบกับการวิเคราะห์การรั่วไหลในอุปกรณ์
นอกจากนี้ ตอนนี้การวิเคราะห์การรั่วไหลยังอยู่ในบริบทภายใน IDE และผสานรวมกับซอร์สโค้ดอย่างเต็มรูปแบบ ซึ่งมีฟีเจอร์ต่างๆ เช่น ไปที่การประกาศ และการเชื่อมต่อโค้ดอื่นๆ ที่เป็นประโยชน์ ซึ่งจะช่วยลดความยุ่งยากและเวลาที่ต้องใช้ในการตรวจสอบและแก้ไขการรั่วไหลของหน่วยความจำได้อย่างมาก
ตัวอย่างการรั่วไหลของหน่วยความจำที่พบบ่อย
หน่วยความจำรั่วเกิดขึ้นเมื่อออบเจ็กต์ยังคงอยู่ในหน่วยความจำนานเกินกว่าอายุการใช้งานที่ตั้งใจไว้ โดยมักมีสาเหตุต่อไปนี้
- เก็บการอ้างอิงถึง Fragment, Activity หรือ View ที่ไม่ได้ใช้งานแล้ว
- การจัดการการอ้างอิงบริบทอย่างไม่เหมาะสม
- การยกเลิกการลงทะเบียน Observer, Listener และ Receiver ไม่ถูกต้อง
- การสร้างการอ้างอิงแบบคงที่ไปยังออบเจ็กต์ที่เชื่อมโยงกับคอมโพเนนต์ที่มีวงจรที่สั้นกว่า
ลองดูสถานการณ์ตัวอย่างต่อไปนี้
| สถานการณ์ | ตัวอย่างที่อิงตาม Compose | ตัวอย่างที่อิงตามการดู |
| การรั่วไหลของบริบท | ตัวอย่าง: แก้ไข: | ตัวอย่าง: แก้ไข: |
| การรั่วไหลของ Listener | ตัวอย่าง: แก้ไข: | ตัวอย่าง: แก้ไข: |
| การรั่วไหลของยอดดู | ตัวอย่าง:
| ตัวอย่าง: แก้ไข: |
ตัดหน่วยความจำเมื่อแอปออกจากสถานะที่มองเห็นได้
Android สามารถเรียกคืนหน่วยความจำจากแอปหรือหยุดแอปทั้งหมดได้หากจำเป็นเพื่อเพิ่มหน่วยความจำสำหรับงานที่สำคัญ ดังที่อธิบายไว้ในภาพรวมของการจัดการหน่วยความจำ โดยปกติแล้ว Android จะเรียกคืนหน่วยความจำจากแอปของคุณเมื่อผู้ใช้มองไม่เห็น เช่น โดยการทิ้งโค้ดและหน้าข้อมูลบางส่วนของแอปในหน่วยความจำ หรือบีบอัดการจัดสรรฮีป เมื่อผู้ใช้กลับมาใช้แอปของคุณอีกครั้งและแอปพยายามเข้าถึงหน่วยความจำบางส่วนที่ระบบเรียกคืนไปแล้ว ระบบปฏิบัติการจะสลับหน่วยความจำนั้นกลับมาตามคำขอ การสลับลักษณะการทำงานนี้อาจช้า และทำให้เกิดอาการกระตุกหรือหยุดชะงักที่ไม่คาดคิดในแอป
หากปล่อยให้ระบบปฏิบัติการตัดสินใจว่าจะเรียกคืนหน่วยความจำใดจากแอป คุณอาจพบว่าระบบปฏิบัติการเรียกคืนหน่วยความจำที่คุณจะต้องใช้ในไม่ช้าหลังจากกลับมาใช้แอปอีกครั้ง ในทางกลับกัน แอปสามารถทิ้งการจัดสรรหน่วยความจำที่สามารถสร้างใหม่ได้ในภายหลังตามต้องการและในราคาต่ำ โดยคุณสามารถใช้อินเทอร์เฟซ ComponentCallbacks2 เพื่อดำเนินการดังกล่าวได้ คุณสามารถใช้ onTrimMemory ในคลาส Activity, Fragment, Service หรือแม้แต่คลาส Application ที่กำหนดเอง การใช้ในApplicationคลาสมีประสิทธิภาพสูงสำหรับการจัดการแคชทั่วโลก
เมธอด Callback onTrimMemory() ที่ระบุจะแจ้งให้แอปทราบถึงเหตุการณ์ที่เกี่ยวข้องกับวงจรหรือหน่วยความจำ ซึ่งเป็นโอกาสที่ดีที่แอปจะลดการใช้งานหน่วยความจำโดยสมัครใจ
ในแง่ของการจัดการวงจรหน่วยความจำ การติดตั้งใช้งานควรเน้นที่ TRIM_MEMORY_UI_HIDDEN และ TRIM_MEMORY_BACKGROUND โดยเฉพาะ ตั้งแต่ Android 14 เป็นต้นมา ระบบได้หยุดส่งการแจ้งเตือนสำหรับค่าคงที่เดิมอื่นๆ ซึ่งเลิกใช้งานอย่างเป็นทางการใน Android 15
TRIM_MEMORY_UI_HIDDEN: สัญญาณนี้บ่งชี้ว่า UI ของแอปพลิเคชันได้เปลี่ยนออกจากมุมมองของผู้ใช้แล้ว ซึ่งจะช่วยให้คุณมีโอกาสที่จะเผยแพร่การจัดสรรหน่วยความจำจำนวนมากที่เชื่อมโยงกับอินเทอร์เฟซอย่างเคร่งครัด เช่น บิตแมป บัฟเฟอร์การเล่นวิดีโอ หรือทรัพยากรภาพเคลื่อนไหวที่ซับซ้อน
TRIM_MEMORY_BACKGROUND: ที่ระดับนี้ กระบวนการของคุณจะอยู่ในเบื้องหลังและตอนนี้เป็นกระบวนการที่อาจถูกสิ้นสุดเพื่อตอบสนองความต้องการหน่วยความจำส่วนกลางของระบบ หากต้องการขยายระยะเวลาที่กระบวนการยังคงอยู่ในสถานะแคช และลดจำนวน Cold Start ของแอป คุณควรปล่อยทรัพยากรทั้งหมดที่สร้างขึ้นใหม่ได้ง่ายเมื่อผู้ใช้กลับมาใช้เซสชันต่อ
import android.content.ComponentCallbacks2 // Other import statements. class MainActivity : AppCompatActivity(), ComponentCallbacks2 { /** * Release memory when the UI becomes hidden or when system resources become low. * @param level the memory-related event that is raised. */ override fun onTrimMemory(level: Int) { if (level >= ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) { // Release memory related to UI elements, such as bitmap caches. } if (level >= ComponentCallbacks2.TRIM_MEMORY_BACKGROUND) { // Release memory related to background processing, such as by // closing a database connection. } } }
หมายเหตุ: onTrimMemory การผสานรวมอาจขึ้นอยู่กับการรองรับ SDK เช่น เกมบางเกมจะใช้เกมเอนจินเพื่อเปิดใช้ความสามารถนี้ โปรดดูเอกสารการเพิ่มประสิทธิภาพหน่วยความจำของเกม
การสังเกตการณ์หน่วยความจำขั้นสูงด้วย ProfilingManager
หากต้องการตรวจหาและวินิจฉัยปัญหาเกี่ยวกับหน่วยความจำในฟิลด์ที่จำลองในเครื่องไม่ได้ คุณควรใช้ประโยชน์จาก ProfilingManager API API ความสามารถในการสังเกตขั้นสูงนี้เปิดตัวใน Android 15 และช่วยให้คุณรวบรวมโปรไฟล์ Perfetto ของผู้ใช้จริงได้แบบเป็นโปรแกรม
สำหรับทีมที่ไม่มีโครงสร้างพื้นฐานเฉพาะเพื่อจัดการและโฮสต์อาร์ติแฟกต์ประสิทธิภาพ Crashlytics กำลังพิจารณาโซลูชันเฉพาะทางเพื่อเพิ่มประสิทธิภาพเวิร์กโฟลว์นี้ โดยขอเชิญนักพัฒนาแอปแสดงความคิดเห็น
Android 17 เปิดตัวทริกเกอร์ที่ขับเคลื่อนด้วยเหตุการณ์ใหม่ โดยเฉพาะอย่างยิ่ง TRIGGER_TYPE_OOM และ TRIGGER_TYPE_ANOMALY
- ทริกเกอร์ OOM จะรวบรวมฮีปดัมป์ของ Java โดยอัตโนมัติในขณะที่เกิดข้อขัดข้อง OutOfMemoryError ซึ่งจะให้สถานะการจัดสรรที่แม่นยำ ระบบจะระบุโปรไฟล์ OOM ที่รวบรวมไว้ในครั้งถัดไปที่แอปเริ่มต้นและลงทะเบียนการเรียกกลับ
registerForAllProfilingResults - ทริกเกอร์ความผิดปกติจะตรวจหาปัญหาด้านประสิทธิภาพที่ร้ายแรง เช่น สแปม Binder มากเกินไปหรือการละเมิดเกณฑ์หน่วยความจำ ความผิดปกติของหน่วยความจำจะส่งการทิ้งหน่วยความจำฮีปก่อนที่ระบบจะสิ้นสุดแอป
val profilingManager = applicationContext.getSystemService(ProfilingManager::class.java) val triggers = ArrayList<ProfilingTrigger>() triggers.add(ProfilingTrigger.Builder( ProfilingTrigger.TRIGGER_TYPE_ANOMALY)) val mainExecutor: Executor = Executors.newSingleThreadExecutor() val resultCallback = Consumer<ProfilingResult> { profilingResult -> if (profilingResult.errorCode != ProfilingResult.ERROR_NONE) { // upload profile result to server for further analysis setupProfileUploadWorker(profilingResult.resultFilePath) } profilingManager.registerForAllProfilingResults(mainExecutor, resultCallback) profilingManager.addProfilingTriggers(triggers)
เมื่อรวบรวมฮีปดัมป์แล้ว คุณจะดาวน์โหลดโปรไฟล์จากเซิร์ฟเวอร์หรือในเครื่องผ่าน adb pull และลากและวางไฟล์ลงใน UI ของ Perfetto ได้ หากต้องการเพิ่มประสิทธิภาพเวิร์กโฟลว์การแก้ไขข้อบกพร่องของหน่วยความจำ ให้ใช้เครื่องมือสำรวจฮีปดัมป์ ซึ่งเป็นมุมมองเริ่มต้นใหม่สำหรับฮีปดัมป์ใน UI ของ Perfetto เครื่องมือนี้มีอินเทอร์เฟซที่ใช้งานง่ายสำหรับการตรวจสอบฮีปดัมป์ของ Java ซึ่งช่วยให้คุณเห็นภาพลำดับชั้นการจัดสรรออบเจ็กต์ คำนวณขนาดหน่วยความจำที่เก็บไว้ และระบุเส้นทางที่สั้นที่สุดจากรูทของระบบจัดการหน่วยความจำที่ไม่ใช้แล้ว การใช้ประโยชน์จาก Heap Dump Explorer จะช่วยให้คุณระบุหน่วยความจำรั่วไหล ออบเจ็กต์ที่เก็บไว้ซึ่งมีขนาดใหญ่ เช่น การจัดสรรบิตแมปมากเกินไป และวิเคราะห์การจัดสรรออบเจ็กต์ฮีปได้ทั้งหมดในที่เดียวอย่างรวดเร็ว
บทสรุป
การเพิ่มประสิทธิภาพไบต์โค้ดด้วย R8 การนำแนวทางปฏิบัติแนะนำในการโหลดรูปภาพมาใช้ และการแก้ไขการรั่วไหลของหน่วยความจำเป็นขั้นตอนสำคัญในการมอบประสบการณ์ของผู้ใช้คุณภาพสูงในขณะที่จัดการทรัพยากรอย่างมีประสิทธิภาพภายใต้แรงกดดัน การใช้มาตรการเชิงรุกเหล่านี้จะช่วยรักษาความเสถียรและประสิทธิภาพของแอป ป้องกันการสิ้นสุดการทำงานโดยไม่คาดคิด และปกป้องบริบทของผู้ใช้ ดูคำแนะนำเกี่ยวกับหน่วยความจำที่ปรับปรุงแล้วเพื่อเพิ่มความเชี่ยวชาญด้านประสิทธิภาพ
-
ฮาวทูการบังคับใช้คุณภาพทางเทคนิคของแบตเตอรี่มาถึงแล้ว: วิธีเพิ่มประสิทธิภาพกรณีการใช้งาน Wake Lock ทั่วไป
Google ทราบดีว่าการที่แบตเตอรี่หมดเร็วเกินไปเป็นสิ่งที่ผู้ใช้ Android กังวลมากที่สุด จึงได้ดำเนินการอย่างจริงจังเพื่อช่วยให้นักพัฒนาแอปสร้างแอปที่ประหยัดพลังงานมากขึ้น
Alice Yuan • อ่าน 8 นาที -
ฮาวทูคู่มือการปรับระดับประสิทธิภาพมี 5 ระดับ เราจะเริ่มจากระดับ 1 ซึ่งเป็นการแนะนำเครื่องมือวัดประสิทธิภาพที่ต้องใช้ความพยายามในการนำไปใช้เพียงเล็กน้อย และจะเพิ่มขึ้นไปจนถึงระดับ 5 ซึ่งเหมาะสำหรับแอปที่มีทรัพยากรในการดูแลกรอบงานประสิทธิภาพที่กำหนดเอง
Alice Yuan • อ่าน 9 นาที -
ฮาวทูเมื่อพัฒนาฟีเจอร์ใหม่ๆ ประสิทธิภาพของแอปมักจะมีความสำคัญรองลงมา อย่างไรก็ตาม แม้ว่านักพัฒนาแอปอาจไม่ได้ให้ความสำคัญกับเรื่องนี้เป็นอันดับแรก แต่ผู้ใช้จะเห็นได้อย่างชัดเจนว่าประสิทธิภาพของแอปคุณด้อยกว่าแอปอื่นๆ ตรงไหน
Ben Weiss • อ่าน 3 นาที
รับข้อมูลเชิงลึกด้านการพัฒนาแอป Android ล่าสุดส่งตรงถึงกล่องจดหมายของคุณทุกสัปดาห์