เริ่มตั้งแต่ 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 วิธีดังนี้
View.isHardwareAccelerated()
ทำรีเทิร์นtrue
หากเชื่อมต่อView
กับฮาร์ดแวร์ที่เร่งการแสดงผลCanvas.isHardwareAccelerated()
แสดงผลtrue
หากCanvas
เป็นการเร่งฮาร์ดแวร์
หากคุณต้องทำการตรวจสอบนี้ในรหัสวาดของคุณ ให้ใช้
Canvas.isHardwareAccelerated()
แทน
ของ View.isHardwareAccelerated()
หากเป็นไปได้ เมื่อการดู
แนบอยู่กับหน้าต่างที่มีการเร่งความเร็วด้วยฮาร์ดแวร์ ก็ยังสามารถวาดได้โดยใช้ฮาร์ดแวร์ที่ไม่ใช่ฮาร์ดแวร์
Canvas แบบเร่ง ตัวอย่างเช่น เมื่อวาดมุมมองเป็นบิตแมปสำหรับการแคช
วัตถุประสงค์
โมเดลภาพวาดของ Android
เมื่อเปิดใช้การเร่งฮาร์ดแวร์ เฟรมเวิร์ก Android จะใช้โมเดลการวาดใหม่ที่ ใช้รายการที่แสดงเพื่อแสดงผลแอปพลิเคชันของคุณบนหน้าจอ เพื่อให้เข้าใจอย่างถ่องแท้ แสดงรายการและผลกระทบที่อาจมีต่อแอปพลิเคชันของคุณ คุณควรเข้าใจว่า Android จะดึงการแสดงผลโดยไม่ต้องเร่งฮาร์ดแวร์ด้วย ส่วนต่อไปนี้จะอธิบาย โมเดลการวาดที่ใช้ซอฟต์แวร์และการเร่งฮาร์ดแวร์
โมเดลการวาดภาพโดยใช้ซอฟต์แวร์
ในรูปแบบการวาดของซอฟต์แวร์ การดูจะวาดด้วย 2 ขั้นตอนต่อไปนี้
- ทำให้ลำดับชั้นไม่ถูกต้อง
- วาดลำดับชั้น
เมื่อใดก็ตามที่แอปพลิเคชันต้องอัปเดต UI บางส่วน แอปพลิเคชันจะเรียก invalidate()
(หรือตัวแปรอย่างใดอย่างหนึ่ง) ในข้อมูลพร็อพเพอร์ตี้ที่มีการเปลี่ยนแปลง
เนื้อหา ระบบจะเผยแพร่ข้อความการโมฆะจนถึงลำดับชั้นการแสดงผลเพื่อประมวลผล
บริเวณของหน้าจอที่ต้องวาดใหม่ (ส่วนที่สกปรก) จากนั้นระบบ Android
จะวาดมุมมองใดๆ ในลำดับชั้นที่ตัดกับพื้นที่สกปรก ขออภัย มี
ข้อเสีย 2 ข้อของโมเดลการวาดนี้
- ประการแรก โมเดลนี้จำเป็นต้องมีการเรียกใช้โค้ดจำนวนมากในการสกัดกั้นแต่ละครั้ง ตัวอย่างเช่น หาก
แอปพลิเคชันของคุณเรียกใช้
invalidate()
บนปุ่ม และ วางอยู่เหนือมุมมองอื่น ระบบ Android จะวาดมุมมองใหม่แม้ว่าจะ มีการเปลี่ยนแปลง - ปัญหาที่สองคือโมเดลการวาดภาพสามารถซ่อนข้อบกพร่องในแอปพลิเคชันของคุณได้ ตั้งแต่
ระบบ Android จะแสดงมุมมองใหม่เมื่อซ้อนทับกับพื้นที่สกปรก ซึ่งเป็นมุมมองที่มีเนื้อหา
ที่เปลี่ยนแปลงอาจมีการวาดใหม่แม้ว่า
invalidate()
จะไม่ใช่ ได้เรียกไว้ เมื่อเกิดกรณีนี้ขึ้น คุณจะต้องใช้ข้อมูลพร็อพเพอร์ตี้อื่นที่ใช้งานไม่ได้ในการรับ พฤติกรรมที่เหมาะสม ลักษณะการทำงานนี้เปลี่ยนแปลงได้ทุกครั้งที่คุณแก้ไขแอปพลิเคชัน เนื่องจาก คุณควรเรียกใช้invalidate()
ตามที่กําหนดเองเสมอ เมื่อใดก็ตามที่คุณแก้ไขข้อมูลหรือสถานะที่มีผลต่อโค้ดวาดของมุมมอง
หมายเหตุ: มุมมองของ Android จะเรียกใช้ invalidate()
โดยอัตโนมัติเมื่อคุณสมบัติมีการเปลี่ยนแปลง เช่น พื้นหลัง
หรือข้อความใน TextView
โมเดลการวาดที่มีการเร่งฮาร์ดแวร์
ระบบ Android ยังคงใช้ invalidate()
และ draw()
เพื่อขออัปเดตหน้าจอและแสดงผลมุมมอง แต่จะต้องจัดการ
การวาดภาพจริงๆ ต่างออกไป แทนที่จะต้องเรียกใช้คำสั่งวาดได้ทันที Android
ระบบจะบันทึกไว้ในรายการที่แสดง ซึ่งมีเอาต์พุตจากลำดับชั้นของการดู
แบบ 3 มิติ การเพิ่มประสิทธิภาพอีกอย่างคือระบบ Android เพียงต้องการบันทึกและอัปเดต
แสดงรายการการดูที่ทำเครื่องหมายว่าสกปรกโดย invalidate()
การโทร จำนวนการดูที่ยังไม่หมดอายุสามารถสร้างขึ้นใหม่ได้ง่ายๆ ด้วยการออก
รายการที่แสดงที่บันทึกไว้ โมเดลภาพวาดใหม่มี 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