เพิ่มประสิทธิภาพอัตราเฟรมด้วยอัตราการรีเฟรชแบบปรับอัตโนมัติ

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

ตั้งแต่ Android 15 เป็นต้นไป เมื่อเปิดใช้ฟีเจอร์อัตราการรีเฟรชแบบปรับได้ (ARR) อุปกรณ์จะลดการคงอัตราการรีเฟรชสูงได้ 2 ด้านดังนี้

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

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

หน้านี้จะอธิบายข้อมูลต่อไปนี้

  • วิธีกำหนดอัตราเฟรมของแต่ละมุมมอง
  • นโยบายทั่วไปเกี่ยวกับวิธีที่ ARR กำหนดอัตราเฟรมที่จะตั้งค่า
  • วิธีลบล้างลักษณะการทำงานของอัตราเฟรมเริ่มต้นด้วยตนเอง

กลไกการโหวตของฟีเจอร์ดู

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

ปัจจุบันยอดดูส่วนใหญ่มีอัตราเฟรม "ปกติ" ซึ่งมักตั้งค่าเป็น 60 Hz หากต้องการอัตราเฟรมที่สูงขึ้น คุณสามารถใช้ API ที่เฉพาะเจาะจงเพื่อปรับแต่งค่ากำหนดได้ โดยปกติแล้วระบบจะเลือกอัตราเฟรมสูงสุด ดูข้อมูลเพิ่มเติมเกี่ยวกับการใช้ API เหล่านี้ได้ที่ส่วนตั้งค่าเฟรม เรตหรือหมวดหมู่ นโยบายทั่วไปเกี่ยวกับอัตราเฟรม อธิบายไว้ในส่วนนโยบาย ARR ทั่วไป

หมวดหมู่ของอัตราเฟรม

ในชั้นเรียน View จะมีหมวดหมู่เฟรมเรตต่างๆ ที่ใช้ในการโหวตได้ คำอธิบายของแต่ละหมวดหมู่มีดังนี้

  • REQUESTED_FRAME_RATE_CATEGORY_DEFAULT: ค่านี้สามารถตั้งค่าให้กลับไปที่ลักษณะการทำงานเริ่มต้น ซึ่งบ่งชี้ว่ามุมมองนี้ไม่มีข้อมูลสำหรับอัตราเฟรม
  • REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE: มุมมองจะไม่มีผลต่ออัตราเฟรมอย่างชัดเจน ซึ่งหมายความว่าแม้ว่า View จะใช้งานอยู่ แต่เฟรมเวิร์กจะไม่พิจารณาเมื่อกำหนดอัตราเฟรม
  • REQUESTED_FRAME_RATE_CATEGORY_NORMAL: แสดงอัตราเฟรมปานกลางที่เหมาะสำหรับภาพเคลื่อนไหวที่ไม่จำเป็นต้องใช้อัตราเฟรมสูงกว่า หรือไม่ได้รับประโยชน์จากความลื่นไหลสูง โดยปกติแล้วจะอยู่ที่ 60 Hz หรือใกล้เคียง
  • REQUESTED_FRAME_RATE_CATEGORY_HIGH: ระบุอัตราเฟรมที่เหมาะสำหรับภาพเคลื่อนไหวที่ต้องใช้อัตราเฟรมสูง ซึ่งอาจเพิ่มความลื่นไหลแต่ก็อาจเพิ่มการใช้พลังงานด้วย

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

อัตราเฟรม

นอกจากหมวดหมู่อัตราเฟรมแล้ว View ยังระบุอัตราเฟรมที่ต้องการได้ด้วย เช่น 30, 60 หรือ 120 Hz เมื่อมีการโหวตอัตราเฟรมหลายครั้ง อัตราเฟรมสุดท้ายจะกำหนดตามกฎต่อไปนี้

  • เป็นค่าที่คูณกัน: หากอัตราเฟรมที่โหวตเป็นค่าที่คูณกัน ระบบจะเลือกค่าสูงสุด เช่น หากมีการโหวต 2 รายการที่ 30 Hz และ 90 Hz ระบบจะเลือก 90 Hz เป็นอัตราเฟรมสุดท้าย
  • ไม่ใช่ค่าที่คูณกัน
    • หากคะแนนใดก็ตามสูงกว่า 60 Hz ระบบจะนับเป็นคะแนน "สูง"
    • หากคะแนนเสียงทั้งหมดเป็น 60 Hz หรือต่ำกว่า ระบบจะนับเป็นคะแนนเสียง "ปกติ"

นอกจากนี้ หากมีทั้งค่าอัตราเฟรมและหมวดหมู่อัตราเฟรม ค่าที่สูงกว่ามักจะเป็นตัวกำหนดอัตราการแสดงผลสุดท้าย ตัวอย่างเช่น หากมีการโหวต 60 Hz และโหวต "สูง" หรือโหวต 120 Hz และโหวต "ปกติ" โดยทั่วไปแล้ว ระบบจะตั้งค่าอัตราการแสดงผลเป็น 120 Hz

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

ตั้งค่าอัตราเฟรมหรือหมวดหมู่

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

คุณใช้ API setRequestedFrameRate() และ getRequestedFrameRate() เพื่อกำหนดอัตราเฟรมหรือ หมวดหมู่ที่ต้องการของมุมมองที่ต้องการได้

Kotlin

// Set the preferred frame rate category to a View

// set the frame rate category to NORMAL
view.requestedFrameRate = View.REQUESTED_FRAME_RATE_CATEGORY_NORMAL
// set the frame rate category to HIGH
view.requestedFrameRate = View.REQUESTED_FRAME_RATE_CATEGORY_HIGH
// reset the frame rate category
view.requestedFrameRate = View.REQUESTED_FRAME_RATE_CATEGORY_DEFAULT

// Set the preferred frame rate to a View

// set the frame rate to 30
view.requestedFrameRate = 30f
// set the frame rate to 60
view.requestedFrameRate = 60f
// set the frame rate to 120
view.requestedFrameRate = 120f

Java

// Set the preferred frame rate category to a View

// set the frame rate category to NORMAL
view.setRequestedFrameRate(View.REQUESTED_FRAME_RATE_CATEGORY_NORMAL);
// set the frame rate category to HIGH
view.setRequestedFrameRate(View.REQUESTED_FRAME_RATE_CATEGORY_HIGH);
// reset the frame rate category
view.setRequestedFrameRate(View.REQUESTED_FRAME_RATE_CATEGORY_DEFAULT);

// Set the preferred frame rate to a View

// set the frame rate to 30
view.setRequestedFrameRate(30);
// set the frame rate to 60
view.setRequestedFrameRate(60);
// set the frame rate to 120
view.setRequestedFrameRate(120);

ดูตัวอย่างการใช้งานได้ที่ TextureView

นโยบาย ARR ทั่วไป

ในส่วนก่อนหน้านี้ เราได้พูดถึงว่าโดยค่าเริ่มต้นแล้วภาพเคลื่อนไหวส่วนใหญ่จะแสดงที่ 60 Hz เนื่องจาก View แต่ละรายการมีการตั้งค่า "ปกติ" เป็นอัตราเฟรมที่ต้องการ อย่างไรก็ตาม มีข้อยกเว้นในกรณีที่อัตราเฟรมเพิ่มขึ้นเป็น "สูง" เพื่อให้ภาพเคลื่อนไหวราบรื่นยิ่งขึ้น

นโยบาย ARR ทั่วไปมีดังนี้

  • การเพิ่มประสิทธิภาพการสัมผัส: เมื่อตรวจพบเหตุการณ์สัมผัส (MotionEvent.ACTION_DOWN) ระบบจะเพิ่มอัตราการรีเฟรชเป็น "สูง" เป็นระยะเวลาหนึ่งหลังจากปล่อยการสัมผัสเพื่อรักษาการตอบสนอง
  • ท่าทางสัมผัสแบบปัด: ท่าทางสัมผัสแบบปัดจะได้รับการจัดการที่แตกต่างกัน โดยอัตราการรีเฟรชจะค่อยๆ ลดลงเมื่อความเร็วในการปัดช้าลง ดูรายละเอียด เกี่ยวกับลักษณะการทำงานนี้ได้ในส่วนการปรับปรุงการเลื่อน
  • การเปิดแอปและการเปลี่ยนหน้าต่าง: อัตราการรีเฟรชจะเพิ่มขึ้นในช่วงเวลาหนึ่งระหว่างการเปิดแอป การเริ่มต้นหน้าต่าง และการเปลี่ยนหน้าต่าง เพื่อให้มั่นใจว่าจะได้รับประสบการณ์ด้านภาพที่ราบรื่น
  • ภาพเคลื่อนไหว: ภาพเคลื่อนไหวที่มีการเคลื่อนไหวหรือการเปลี่ยนแปลงขนาดจะได้รับอัตราการรีเฟรชที่สูงขึ้นโดยอัตโนมัติเพื่อเพิ่มความราบรื่นเมื่อตำแหน่งหรือขนาดของ View เปลี่ยนแปลง
  • SurfaceView และ TextureView: อัตราเฟรมที่ตั้งค่าอย่างชัดเจนสำหรับ TextureView และ SurfaceView จะได้รับการพิจารณาและนำไปใช้ ตามนั้น

เปิดและปิดใช้การเพิ่มประสิทธิภาพการสัมผัส

คุณเปิดและ/หรือปิดใช้การเพิ่มประสิทธิภาพการแตะได้ที่ระดับ Window โดยค่าเริ่มต้น เมื่อผู้ใช้แตะและยกนิ้วออกจากหน้าจอ อัตราการแสดงผล จะเพิ่มขึ้นเป็นระยะเวลาหนึ่ง API setFrameRateBoostOnTouchEnabled() และ getFrameRateBoostOnTouchEnabled() ช่วยให้คุณป้องกันไม่ให้ อัตราการแสดงผลเพิ่มขึ้นเมื่อมีการแตะ Window ที่เฉพาะเจาะจง

Kotlin

// disable touch boost on a Window
window.isFrameRateBoostOnTouchEnabled = false 
// enable touch boost on a Window
window.isFrameRateBoostOnTouchEnabled = true
// check if touch boost is enabled on a Window
val isTouchBoostEnabled = window.isFrameRateBoostOnTouchEnabled

Java

// disable touch boost on a Window
window.setFrameRateBoostOnTouchEnabled(false)
// enable touch boost on a Window
window.setFrameRateBoostOnTouchEnabled(true)
// check if touch boost is enabled on a Window
window.getFrameRateBoostOnTouchEnabled()

การปรับปรุงการเลื่อน

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

การปรับปรุงนี้มีผลกับคอมโพเนนต์ UI ที่เลื่อนได้โดยเฉพาะ ซึ่งรวมถึง ScrollView, ListView และ GridView และอาจไม่พร้อมใช้งานสำหรับการติดตั้งใช้งานที่กำหนดเองทั้งหมด

ฟีเจอร์การเลื่อน ARR พร้อมใช้งานสำหรับ RecyclerView และ NestedScrollView หากต้องการเปิดใช้ฟีเจอร์นี้ในแอป ให้อัปเกรดเป็นAndroidX.recyclerviewและAndroidX.coreเวอร์ชันล่าสุด ดูรายละเอียดในตารางต่อไปนี้

คลัง

เวอร์ชัน

AndroidX.recyclerview

1.4.0

AndroidX.core

1.15.0

ตั้งค่าข้อมูลความเร็ว

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

Kotlin

// set the velocity to a View (1000 pixels/Second)
view.frameContentVelocity = 1000f
// get the velocity of a View
val velocity = view.frameContentVelocity

Java

// set the velocity to a View
view.setFrameContentVelocity(velocity);

// get the velocity of a View
final float velocity = view.getFrameContentVelocity()

ดูตัวอย่างเพิ่มเติมได้ที่ RecyclerView และ ScrollView หากไม่สามารถรับข้อมูลที่จำเป็นจาก Scroller หรือ OverScroller ให้คำนวณ ความเร็วของเนื้อหา (พิกเซลต่อวินาที) ด้วยตนเองเพื่อตั้งค่าความเร็วอย่างถูกต้อง

โปรดทราบว่าหากมีการเรียกใช้ setFrameContentVelocity() และ getFrameContentVelocity() ในมุมมองที่เป็นคอมโพเนนต์ที่เลื่อนไม่ได้ การเรียกใช้ดังกล่าวจะไม่มีผล เนื่องจากระบบจะทริกเกอร์การเคลื่อนไหวโดยอัตโนมัติ ซึ่งจะเพิ่มอัตราเฟรมตามนโยบายปัจจุบัน

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

เปิดและปิดใช้ ARR

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

หากต้องการเปิดหรือปิดใช้ ARR ให้ใช้ API setFrameRatePowerSavingsBalanced() ใน Window หรือใช้ API isFrameRatePowerSavingsBalanced() ผ่านไฟล์ styles.xml

ข้อมูลโค้ดต่อไปนี้แสดงวิธีเปิดหรือปิดใช้ ARR ใน Window

Kotlin

// disable ARR on a Window
window.isFrameRatePowerSavingsBalanced = false 
// enable ARR on a Window
window.isFrameRatePowerSavingsBalanced = true  
// check if ARR is enabled on a Window
val isAdaptiveRefreshRateEnabled = window.isFrameRatePowerSavingsBalanced

Java

// disable ARR on a Window
window.setFrameRatePowerSavingsBalanced(false)
// enable ARR on a Window
window.setFrameRatePowerSavingsBalanced(true)
// check if ARR is enabled on a Window
window.isFrameRatePowerSavingsBalanced()

หากต้องการปิดใช้ ARR ผ่านไฟล์ styles.xml ให้เพิ่มรายการต่อไปนี้ลงในสไตล์ใน res/values/styles.xml

<style name="frameRatePowerSavingsBalancedDisabled">
    <item name="android:windowIsFrameRatePowerSavingsBalanced">false</item>
</style>

ARR สำหรับ Compose

นอกจากนี้ Compose 1.9 ยังรองรับอัตราการรีเฟรชแบบปรับอัตโนมัติด้วย ในระบบ View คุณใช้วิธี setRequestedFrameRate() เพื่อ ขออัตราเฟรมที่เฉพาะเจาะจงสำหรับ View ใน Compose ตัวแก้ไขใหม่ช่วยให้คุณ ระบุอัตราเฟรมสำหรับ Composable ได้ ตัวแก้ไขนี้ทํางานคล้ายกับ setRequestedFrameRate() โดยยอมรับค่าอัตราเฟรมที่เป็นบวก (ในหน่วย Hz) หรือหมวดหมู่อัตราเฟรมที่กําหนดไว้ล่วงหน้า FrameRateCategory

ลายเซ็นสำหรับ API มีดังนี้

ในข้อมูลโค้ดด้านล่าง ตัวแก้ไขอัตราเฟรมใหม่ (Modifier.requestedFrameRate(120f)) จะใช้กับ Text ที่ประกอบได้ ตัวปรับนี้ทำให้ Text composable ขออัตราเฟรมที่ต้องการเป็น 120 เมื่อวาดหรือเคลื่อนไหว (เช่น มีการเปลี่ยนแปลงความทึบแสง)

var targetAlpha by remember { mutableFloatStateOf(1f) }
val alpha by
    animateFloatAsState(
        targetValue = targetAlpha,
        animationSpec = tween(durationMillis = 1000)
    )

Button(
    onClick = { targetAlpha = if (targetAlpha == 1f) 0.2f else 1f },
    modifier =
        Modifier.background(LocalContentColor.current.copy(alpha = alpha))
) {
    Text(
        text = "Click",
        color = LocalContentColor.current.copy(alpha = alpha),
        modifier = Modifier.preferredFrameRate(120f)
     // You can also pass frame rate category such as FrameRateCategory.High  to increase the frame rate
    )
  }

จากนั้นระบบจะรวบรวมอัตราเฟรมที่ต้องการจาก Composable ทั้งหมดและ รวมเข้าด้วยกันเพื่อกำหนดอัตราเฟรมสุดท้ายสำหรับแต่ละเฟรม ดูรายละเอียดเพิ่มเติมได้ที่ SetFrameRateSample และ SetFrameRateCategorySample