การเร่งฮาร์ดแวร์

เริ่มตั้งแต่ Android 3.0 (API ระดับ 11) ไปป์ไลน์การแสดงภาพ 2 มิติของ Android จะรองรับฮาร์ดแวร์ การเร่งความเร็ว หมายความว่าการดำเนินการวาดทั้งหมดที่ดำเนินการใน ผืนผ้าใบของ View ใช้ GPU เนื่องจากต้องเพิ่มทรัพยากรที่จำเป็นสำหรับการเปิดใช้ การเร่งฮาร์ดแวร์จะทำให้แอปของคุณใช้ RAM มากขึ้น

ระบบจะเปิดใช้การเร่งฮาร์ดแวร์โดยค่าเริ่มต้นหากระดับ API เป้าหมายของคุณ >=14 แต่สามารถ เปิดใช้อย่างชัดแจ้ง หากแอปพลิเคชันของคุณใช้เฉพาะมุมมองมาตรฐานและ Drawable วินาที การเปิดใช้โดยรวมจะไม่ทำให้การวาดที่ไม่พึงประสงค์ เอฟเฟกต์ อย่างไรก็ตาม เนื่องจากการเร่งฮาร์ดแวร์ไม่ได้รับการสนับสนุนสำหรับการวาดภาพ 2 มิติทั้งหมด การดำเนินการ การเปิดอาจมีผลต่อมุมมองที่กำหนดเองหรือการดึงดูดการเรียก ปัญหา ปกติแล้วจะปรากฏออกมาเป็นองค์ประกอบที่มองไม่เห็น ข้อยกเว้น หรือเป็นพิกเซลที่แสดงผลไม่ถูกต้อง ถึง Android มีตัวเลือกให้คุณเปิดหรือปิดใช้ การเร่งฮาร์ดแวร์ ระดับต่างๆ ดูควบคุมการเร่งฮาร์ดแวร์

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

ดูข้อมูลเพิ่มเติมที่ OpenGL ที่ใช้ API เฟรมเวิร์ก และ Renderscript

ควบคุมการเร่งฮาร์ดแวร์

คุณสามารถควบคุมการเร่งฮาร์ดแวร์ได้ที่ระดับต่อไปนี้

  • การสมัคร
  • กิจกรรม
  • หน้าต่าง
  • ดู

ระดับแอปพลิเคชัน

ในไฟล์ Manifest ของ Android ให้เพิ่มแอตทริบิวต์ต่อไปนี้ลงในส่วน แท็ก <application> เพื่อเปิดใช้การเร่งฮาร์ดแวร์สำหรับทั้ง แอปพลิเคชัน:

<application android:hardwareAccelerated="true" ...>

ระดับกิจกรรม

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

<application android:hardwareAccelerated="true">
    <activity ... />
    <activity android:hardwareAccelerated="false" />
</application>

ระดับหน้าต่าง

หากคุณต้องการการควบคุมที่ละเอียดยิ่งขึ้น คุณสามารถเปิดใช้การเร่งฮาร์ดแวร์สำหรับ ที่มีรหัสต่อไปนี้

Kotlin

window.setFlags(
        WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
        WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED
)

Java

getWindow().setFlags(
    WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
    WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);

หมายเหตุ: ปัจจุบันคุณไม่สามารถปิดใช้การเร่งฮาร์ดแวร์ที่ ระดับหน้าต่าง

ระดับข้อมูลพร็อพเพอร์ตี้

คุณสามารถปิดใช้การเร่งฮาร์ดแวร์สำหรับมุมมองใดมุมมองหนึ่งขณะรันไทม์ด้วยฟังก์ชัน รหัสต่อไปนี้:

Kotlin

myView.setLayerType(View.LAYER_TYPE_SOFTWARE, null)

Java

myView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);

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

ระบุว่ามุมมองเป็นการเร่งฮาร์ดแวร์หรือไม่

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

คุณสามารถตรวจสอบว่าแอปพลิเคชันมีการเร่งความเร็วด้วยฮาร์ดแวร์หรือไม่มี 2 วิธีดังนี้

หากคุณต้องทำการตรวจสอบนี้ในรหัสวาดของคุณ ให้ใช้ Canvas.isHardwareAccelerated() แทน ของ View.isHardwareAccelerated() หากเป็นไปได้ เมื่อการดู แนบอยู่กับหน้าต่างที่มีการเร่งความเร็วด้วยฮาร์ดแวร์ ก็ยังสามารถวาดได้โดยใช้ฮาร์ดแวร์ที่ไม่ใช่ฮาร์ดแวร์ Canvas แบบเร่ง ตัวอย่างเช่น เมื่อวาดมุมมองเป็นบิตแมปสำหรับการแคช วัตถุประสงค์

โมเดลภาพวาดของ Android

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

โมเดลการวาดภาพโดยใช้ซอฟต์แวร์

ในรูปแบบการวาดของซอฟต์แวร์ การดูจะวาดด้วย 2 ขั้นตอนต่อไปนี้

  1. ทำให้ลำดับชั้นไม่ถูกต้อง
  2. วาดลำดับชั้น

เมื่อใดก็ตามที่แอปพลิเคชันต้องอัปเดต UI บางส่วน แอปพลิเคชันจะเรียก invalidate() (หรือตัวแปรอย่างใดอย่างหนึ่ง) ในข้อมูลพร็อพเพอร์ตี้ที่มีการเปลี่ยนแปลง เนื้อหา ระบบจะเผยแพร่ข้อความการโมฆะจนถึงลำดับชั้นการแสดงผลเพื่อประมวลผล บริเวณของหน้าจอที่ต้องวาดใหม่ (ส่วนที่สกปรก) จากนั้นระบบ Android จะวาดมุมมองใดๆ ในลำดับชั้นที่ตัดกับพื้นที่สกปรก ขออภัย มี ข้อเสีย 2 ข้อของโมเดลการวาดนี้

  • ประการแรก โมเดลนี้จำเป็นต้องมีการเรียกใช้โค้ดจำนวนมากในการสกัดกั้นแต่ละครั้ง ตัวอย่างเช่น หาก แอปพลิเคชันของคุณเรียกใช้ invalidate() บนปุ่ม และ วางอยู่เหนือมุมมองอื่น ระบบ Android จะวาดมุมมองใหม่แม้ว่าจะ มีการเปลี่ยนแปลง
  • ปัญหาที่สองคือโมเดลการวาดภาพสามารถซ่อนข้อบกพร่องในแอปพลิเคชันของคุณได้ ตั้งแต่ ระบบ Android จะแสดงมุมมองใหม่เมื่อซ้อนทับกับพื้นที่สกปรก ซึ่งเป็นมุมมองที่มีเนื้อหา ที่เปลี่ยนแปลงอาจมีการวาดใหม่แม้ว่า invalidate() จะไม่ใช่ ได้เรียกไว้ เมื่อเกิดกรณีนี้ขึ้น คุณจะต้องใช้ข้อมูลพร็อพเพอร์ตี้อื่นที่ใช้งานไม่ได้ในการรับ พฤติกรรมที่เหมาะสม ลักษณะการทำงานนี้เปลี่ยนแปลงได้ทุกครั้งที่คุณแก้ไขแอปพลิเคชัน เนื่องจาก คุณควรเรียกใช้ invalidate() ตามที่กําหนดเองเสมอ เมื่อใดก็ตามที่คุณแก้ไขข้อมูลหรือสถานะที่มีผลต่อโค้ดวาดของมุมมอง

หมายเหตุ: มุมมองของ Android จะเรียกใช้ invalidate() โดยอัตโนมัติเมื่อคุณสมบัติมีการเปลี่ยนแปลง เช่น พื้นหลัง หรือข้อความใน TextView

โมเดลการวาดที่มีการเร่งฮาร์ดแวร์

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

  1. ทำให้ลำดับชั้นไม่ถูกต้อง
  2. บันทึกและอัปเดตรายการที่แสดง
  3. วาดรายการแสดงผล

เมื่อใช้โมเดลนี้ คุณจะไม่สามารถอาศัยมุมมองที่ตัดกับพื้นที่สกปรกเพื่อเรียกใช้เมธอด draw() เพื่อให้มั่นใจว่าระบบ Android มีการบันทึก รายการที่แสดงของมุมมอง คุณต้องโทรหา invalidate() การลืม การทำเช่นนั้นจะทำให้มุมมองดูเหมือนเดิมแม้ว่าจะมีการเปลี่ยนแปลงแล้วก็ตาม

การใช้รายการที่แสดงก็ส่งผลดีต่อประสิทธิภาพของภาพเคลื่อนไหวเช่นกัน เนื่องจากการตั้งค่าคุณสมบัติเฉพาะ เช่น อัลฟาหรือการหมุนเวียน ไม่จำเป็นต้องทำให้มุมมองเป้าหมายเป็นโมฆะ (เนื่องจาก โดยอัตโนมัติ) การเพิ่มประสิทธิภาพนี้ยังนำไปใช้กับมุมมองที่มีรายการที่แสดง (ทุกๆ มุมมองเมื่อ แอปพลิเคชันมีการเร่งฮาร์ดแวร์) เช่น สมมติว่ามี LinearLayout ที่มี ListView อยู่เหนือ Button รายการที่แสดงสำหรับ LinearLayout มีลักษณะ ดังนี้

  • DrawDisplayList(มุมมองรายการ)
  • รายการแสดงการวาด(ปุ่ม)

ให้สมมติว่าในตอนนี้คุณต้องการเปลี่ยนความทึบแสงของ ListView หลัง กำลังเรียกใช้ setAlpha(0.5f) ใน ListView รายการที่แสดงตอนนี้ มี:

  • SaveLayerAlpha(0.5)
  • DrawDisplayList(มุมมองรายการ)
  • คืนค่า
  • รายการแสดงการวาด(ปุ่ม)

ไม่มีการเรียกใช้โค้ดภาพวาดที่ซับซ้อนของ ListView แต่ ระบบอัปเดตเฉพาะรายการแสดงผลของ LinearLayout ที่ใช้ง่ายขึ้นมาก ใน แอปพลิเคชันที่ไม่มีการเร่งฮาร์ดแวร์ รหัสวาดของทั้งรายการและ ผู้ปกครองจะดำเนินการอีกครั้ง

รองรับการดำเนินการวาด

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

ตารางต่อไปนี้อธิบายระดับการสนับสนุนของการดำเนินการต่างๆ ในระดับ API

API ระดับแรกที่รองรับ
Canvas
DrawBitmapMesh() (อาร์เรย์สี) 18
DrawPicture() 23
DrawPosText() 16
DrawTextOnPath() 16
DrawVertices() 29
setDrawFilter() 16
ClipsPath() 18
ClipRegion() 18
ClipRect(ภูมิภาค.Op.XOR) 18
ClipRect(Region.Op.Difference) 18
ClipRect(Region.Op.Reverseleft) 18
ClipRect() ที่มีการหมุน/มุมมอง 18
สี
setAntiAlias() (สำหรับข้อความ) 18
setAntiAlias() (สำหรับบรรทัด) 16
setFilterBitmap() 17
setLinearText()
setMaskFilter()
setPathEffect() (สำหรับบรรทัด) 28
setShadowLayer() (นอกเหนือจากข้อความ) 28
setStrokeCap() (สำหรับบรรทัด) 18
setStrokeCap() (สำหรับคะแนน) 19
setSubpixelText() 28
Xfermode
PorterDuff.Mode.DARKEN (เฟรมบัฟเฟอร์) 28
PorterDuff.Mode.LIGHTEN (เฟรมบัฟเฟอร์) 28
PorterDuff.Mode.OVERLAY (Framebuffer) 28
ให้แสงเงา
ComposeShader ภายใน ComposeShader 28
ตัวปรับแสงเงาประเภทเดียวกันภายใน ComposeShader 28
เมตริกซ์ภายในบน ComposeShader 18

การปรับขนาด Canvas

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

ตารางต่อไปนี้แสดงเมื่อมีการเปลี่ยนการติดตั้งใช้งานเพื่อจัดการกับขนาดใหญ่อย่างถูกต้อง
การดำเนินการวาดภาพเพื่อปรับขนาด API ระดับแรกที่รองรับ
DrawText() 18
DrawPosText() 28
DrawTextOnPath() 28
รูปทรงง่ายๆ* 17
รูปร่างที่ซับซ้อน* 28
DrawPath() 28
เลเยอร์เงา 28

หมายเหตุ: "แบบง่าย" รูปทรงต่างๆ ได้แก่ drawRect() drawCircle(), drawOval(), drawRoundRect() และ drawArc() (มี useCenter=false) คำสั่งที่ออกโดยโปรแกรม Paint ที่ไม่มีส่วน PathEffect และไม่มีการรวมที่ไม่ใช่ค่าเริ่มต้น (ผ่าน setStrokeJoin() / setStrokeMiter()) อินสแตนซ์อื่นๆ ของคำสั่งวาดเหล่านี้จะอยู่ในส่วน "ซับซ้อน" ใน จากแผนภูมิด้านบน

ถ้าแอปพลิเคชันของคุณได้รับผลกระทบจากคุณลักษณะหรือข้อจำกัดใดๆ ที่ขาดหายไปเหล่านี้ คุณสามารถ ปิดการเร่งฮาร์ดแวร์เฉพาะในส่วนที่ได้รับผลกระทบของแอปพลิเคชันของคุณด้วยการเรียก setLayerType(View.LAYER_TYPE_SOFTWARE, null) วิธีนี้จะช่วยให้คุณ ยังคงใช้ประโยชน์จากการเร่งฮาร์ดแวร์ ในที่อื่นๆ ได้ ดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีเปิดใช้ควบคุมการเร่งฮาร์ดแวร์ และปิดใช้การเร่งฮาร์ดแวร์ที่ระดับต่างๆ ในแอปพลิเคชัน

ดูเลเยอร์

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

เริ่มตั้งแต่ Android 3.0 (API ระดับ 11) คุณจะควบคุมวิธีและเวลาที่ควรใช้เลเยอร์ได้มากขึ้น ด้วยเมธอด View.setLayerType() API นี้ใช้เวลา 2 พารามิเตอร์: ประเภทเลเยอร์ที่คุณต้องการใช้ และ Paint ซึ่งไม่บังคับ ที่อธิบายวิธีการประกอบเลเยอร์ คุณสามารถใช้พารามิเตอร์ Paint เพื่อใช้ฟิลเตอร์สี โหมดผสานพิเศษ หรือความทึบแสงกับ มุมมองหนึ่งสามารถใช้เลเยอร์หนึ่งใน 3 ประเภทต่อไปนี้

  • LAYER_TYPE_NONE: มุมมองจะแสดงผลตามปกติและไม่มีการสำรองข้อมูล จากบัฟเฟอร์นอกหน้าจอ นี่คือลักษณะการทำงานเริ่มต้น
  • LAYER_TYPE_HARDWARE: มุมมองจะแสดงผลในฮาร์ดแวร์เป็น พื้นผิวฮาร์ดแวร์ หากแอปพลิเคชันมีการเร่งฮาร์ดแวร์ หากแอปพลิเคชันไม่ใช่ฮาร์ดแวร์ แบบเร่ง เลเยอร์ประเภทนี้จะทํางานเหมือนกับ LAYER_TYPE_SOFTWARE
  • LAYER_TYPE_SOFTWARE: มุมมองจะแสดงผลในซอฟต์แวร์เป็น บิตแมป

ประเภทของเลเยอร์ที่คุณใช้จะขึ้นอยู่กับเป้าหมายของคุณ ดังนี้

  • ประสิทธิภาพ: ใช้ประเภทเลเยอร์ฮาร์ดแวร์ในการแสดงผลมุมมองในฮาร์ดแวร์ ของ Google เมื่อแสดงผลมุมมองในเลเยอร์แล้ว ก็ไม่จำเป็นต้องเรียกใช้โค้ดวาดของมุมมองนั้น จนกว่ามุมมองจะโทรหา invalidate() ภาพเคลื่อนไหวบางอย่าง เช่น ภาพเคลื่อนไหวนี้ สามารถนำ ไปใส่บนเลเยอร์โดยตรง ซึ่งมีประสิทธิภาพมาก ที่ GPU ทำงาน
  • เอฟเฟกต์ภาพ: ใช้ประเภทเลเยอร์ฮาร์ดแวร์หรือซอฟต์แวร์ และ Paint เพื่อใช้การตกแต่งภาพแบบพิเศษกับมุมมอง ตัวอย่างเช่น คุณสามารถ วาดมุมมองเป็นสีขาวดำโดยใช้ ColorMatrixColorFilter
  • ความเข้ากันได้: ใช้ประเภทเลเยอร์ของซอฟต์แวร์เพื่อบังคับให้แสดงผลมุมมองใน ซอฟต์แวร์ หากการดูที่ใช้การเร่งความเร็วด้วยฮาร์ดแวร์ (เช่น หากทั้ง เป็นฮาร์ดแวร์ที่รองรับ) มีปัญหาในการแสดงผล ซึ่งเป็นวิธีทำงานที่ง่าย เกี่ยวกับข้อจำกัดในการแสดงผลของฮาร์ดแวร์ ไปป์ไลน์

ดูเลเยอร์และภาพเคลื่อนไหว

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

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

  • alpha: เปลี่ยนความทึบแสงของเลเยอร์
  • x y translationX translationY เปลี่ยนตำแหน่งของเลเยอร์
  • scaleX, scaleY: เปลี่ยนขนาดของเลเยอร์
  • rotation, rotationX, rotationY: เปลี่ยนแปลง การวางแนวของเลเยอร์ในพื้นที่ 3 มิติ
  • pivotX, pivotY: เปลี่ยนต้นทางการเปลี่ยนรูปแบบของเลเยอร์

พร็อพเพอร์ตี้เหล่านี้เป็นชื่อที่ใช้เมื่อทำให้มุมมองเคลื่อนไหวด้วย ObjectAnimator หากคุณต้องการเข้าถึงคุณสมบัติเหล่านี้ ให้โทรหา Setter หรือ Getter ตัวอย่างเช่น หากต้องการแก้ไขพร็อพเพอร์ตี้อัลฟ่า ให้เรียก setAlpha() ข้อมูลโค้ดต่อไปนี้เป็นวิธีที่มีประสิทธิภาพมากที่สุด เพื่อหมุนมุมมองในมุมมอง 3 มิติรอบแกน Y โดยทำดังนี้

Kotlin

view.setLayerType(View.LAYER_TYPE_HARDWARE, null)
ObjectAnimator.ofFloat(view, "rotationY", 180f).start()

Java

view.setLayerType(View.LAYER_TYPE_HARDWARE, null);
ObjectAnimator.ofFloat(view, "rotationY", 180).start();

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

Kotlin

view.setLayerType(View.LAYER_TYPE_HARDWARE, null)
ObjectAnimator.ofFloat(view, "rotationY", 180f).apply {
    addListener(object : AnimatorListenerAdapter() {
        override fun onAnimationEnd(animation: Animator) {
            view.setLayerType(View.LAYER_TYPE_NONE, null)
        }
    })
    start()
}

Java

view.setLayerType(View.LAYER_TYPE_HARDWARE, null);
ObjectAnimator animator = ObjectAnimator.ofFloat(view, "rotationY", 180);
animator.addListener(new AnimatorListenerAdapter() {
    @Override
    public void onAnimationEnd(Animator animation) {
        view.setLayerType(View.LAYER_TYPE_NONE, null);
    }
});
animator.start();

ดูข้อมูลเพิ่มเติมเกี่ยวกับภาพเคลื่อนไหวของพร็อพเพอร์ตี้ได้ที่ภาพเคลื่อนไหวของพร็อพเพอร์ตี้

กลเม็ดเคล็ดลับ

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

ลดจำนวนยอดดูในแอปพลิเคชัน
ยิ่งระบบวาดมุมมองได้มากเท่าใด ก็จะยิ่งช้าลงเท่านั้น รายการนี้มีผลกับซอฟต์แวร์ การแสดงผลด้วยไปป์ไลน์ การลดยอดดูเป็นวิธีที่ง่ายที่สุดวิธีหนึ่งในการเพิ่มประสิทธิภาพ UI
หลีกเลี่ยงการวาดทับ
อย่าวาดเลเยอร์ทับกันมากเกินไป นำมุมมองที่ไม่มีประสิทธิภาพออก ถูกบดบังด้วยมุมมองที่ไม่ชัดเจนอื่นๆ ด้านบน ถ้าคุณต้องการวาดหลายๆ เลเยอร์ที่ผสานกันอยู่ด้านบน ให้พิจารณารวมเนื้อหาเหล่านั้นไว้ในเลเยอร์เดียว หลักการทั่วไปที่ดี ฮาร์ดแวร์จะต้องไม่วาดเกิน 2.5 เท่าของจำนวนพิกเซลบนหน้าจอต่อเฟรม (จำนวนพิกเซลโปร่งใสในหน่วยบิตแมป)
ไม่สร้างวัตถุการแสดงผลในวิธีการวาด
ข้อผิดพลาดที่พบบ่อยคือการสร้าง Paint ใหม่หรือ Path ใหม่ทุกครั้งที่มีการเรียกใช้วิธีการแสดงผล วิธีนี้จะทำให้ถังขยะ ให้เรียกใช้บ่อยขึ้น รวมทั้งเลี่ยงการแคชและการเพิ่มประสิทธิภาพในฮาร์ดแวร์ด้วย ไปป์ไลน์
อย่าแก้ไขรูปร่างบ่อยเกินไป
เช่น รูปร่าง เส้นทาง และวงกลมที่ซับซ้อนจะแสดงผลโดยใช้มาสก์พื้นผิว ทุก เวลาที่คุณสร้างหรือแก้ไขเส้นทาง ไปป์ไลน์ฮาร์ดแวร์จะสร้างมาส์กใหม่ ซึ่งสามารถ มีราคาแพง
อย่าแก้ไขบิตแมปบ่อยเกินไป
ทุกครั้งที่คุณเปลี่ยนเนื้อหาของบิตแมป จะมีการอัปโหลดอีกครั้งเป็นพื้นผิว GPU ในครั้งถัดไปที่คุณวาด
ใช้อัลฟ่าอย่างระมัดระวัง
เมื่อคุณทำให้มุมมองโปร่งแสงโดยใช้ setAlpha() AlphaAnimation หรือ ObjectAnimator แสดงในบัฟเฟอร์นอกหน้าจอ ซึ่งจะเพิ่มอัตราการส่งโฆษณาที่จำเป็นเป็น 2 เท่า เมื่อใช้อัลฟ่า ในมุมมองขนาดใหญ่มาก ให้พิจารณาตั้งค่าประเภทเลเยอร์ของมุมมองเป็น LAYER_TYPE_HARDWARE