כשמפעילים אנימציה ב-Android, המסך לרוב מתרענן בקצב המקסימלי כדי להבטיח חוויה חלקה. שיעור הרענון הגבוה הזה לא נחוץ לאנימציות קטנות כמו סרגלי התקדמות וויזואליזציות של אודיו, והוא גורם לצריכת אנרגיה גבוהה.
החל מ-Android 15, בעזרת התכונה 'קצב רענון דינמי' (ARR), מכשירים עם קצב רענון גבוה יכולים להפחית את זמן השהייה של קצב הרענון הגבוה בשני תחומים:
- בעזרת אופטימיזציות חדשות לניהול קצב הפריימים בפלטפורמה, אפליקציות יכולות לבצע רינדור בקצב פריימים נמוך כברירת מחדל, ולהגביר את קצב הפריימים רק כשצריך.
- קצב הרענון של המסך מותאם באופן דינמי לקצב העיבוד של התוכן ללא תנודות.
רוב האפליקציות ייהנו מ-ARR בלי צורך בשינויים, אבל אפשר גם לשנות את התנהגות ברירת המחדל של קצב הפריימים לפי הצורך.
בדף הזה נסביר את הנושאים הבאים:
- איך נקבע קצב הפריימים של כל תצוגה מפורטת.
- המדיניות הכללית לגבי האופן שבו ARR קובע את קצב הפריימים.
- איך אפשר לשנות ידנית את התנהגות ברירת המחדל של קצב הפריימים.
מנגנון הצבעה בתצוגה
במערכת התצוגה של Android, כל תצוגה בהיררכיית ממשק המשתמש יכולה להגדיר את קצב הפריימים המועדף שלה. ההעדפות האלה נאספות ומשולבות כדי לקבוע את קצב הפריימים הסופי של כל פרים. הדבר מתבצע באמצעות מנגנון הצבעה שבו כל תצוגה מצביעה על סמך מאפיין קצב הפריימים שלה, שיכול להיות קטגוריה או קצב ספציפי. בדרך כלל, התצוגות מצביעות כשהן מצוירות או מתעדכנות. ההצבעות האלה משולבות כדי לקבוע את קצב הפריימים הסופי, ואז הוא נשלח לשכבה ברמה נמוכה יותר כרמז לעיבוד.
ברוב התצוגות, קצב הפריימים מוגדר כברירת מחדל ל'רגיל', ולרוב הוא מוגדר ל-60 הרץ. כדי להגדיר קצב פריימים גבוה יותר, אפשר להשתמש בממשקי API ספציפיים כדי להתאים אישית את ההעדפות. בדרך כלל המערכת בוחרת את קצב הפריימים הגבוה ביותר. מידע נוסף על השימוש בממשקי ה-API האלה זמין בקטע הגדרת קצב הפריימים או הקטגוריה. המדיניות הכללית בנושא קצב פריימים מתוארת בקטע מדיניות כללית בנושא ARR.
קטגוריות של קצב פריימים
בסיווג View
יש קטגוריות שונות של קצב פריימים שאפשר להשתמש בהן בהצבעה. התיאור של כל קטגוריה הוא:
-
REQUESTED_FRAME_RATE_CATEGORY_DEFAULT
: אפשר להגדיר את הערך הזה כדי לחזור להתנהגות ברירת המחדל, כלומר לציין שלתצוגה הזו אין נתונים לגבי קצב הפריימים. -
REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE
: התצוגה לא תשפיע באופן מפורש על קצב הפריימים. המשמעות היא שגם אם התצוגה פעילה, המסגרת לא תתייחס אליה כשתקבע את קצב הפריימים -
REQUESTED_FRAME_RATE_CATEGORY_NORMAL
: מציין קצב פריימים בינוני שמתאים לאנימציות שלא דורשות קצב פריימים גבוה יותר, או שלא מפיקות תועלת משינויים חלקים. בדרך כלל מדובר ב-60 הרץ או בערך הזה. -
REQUESTED_FRAME_RATE_CATEGORY_HIGH
: מציין קצב פריימים שמתאים לאנימציות שדורשות קצב פריימים גבוה, מה שעשוי לשפר את החלקות אבל גם להגדיל את צריכת החשמל.
התצוגה תצביע רק אם נדרש ציור מחדש. קצב הפריימים הסופי נקבע לפי מספר ההצבעות הגבוה ביותר. לדוגמה, אם כל ההצבעות הן לסטטוס 'רגיל', הסטטוס שנבחר הוא 'רגיל'. אם יש הצבעות גם על "רגיל" וגם על "גבוה", המערכת בוחרת באפשרות "גבוה".
קצב פריימים
בנוסף לקטגוריות של קצב פריימים, אפשר גם לציין צפייה בקצב פריימים מועדף, כמו 30, 60 או 120 הרץ. כשמצביעים על כמה קצבי פריימים, קצב הפריימים הסופי נקבע לפי הכללים הבאים:
- כפולות אחת של השנייה: אם קצב הפריימים שנבחר הוא כפולה של קצב פריימים אחר, הערך הגבוה ביותר נבחר. לדוגמה, אם יש שתי הצבעות – 30 Hz ו-90 Hz – נבחר 90 Hz כקצב הפריימים הסופי.
- לא מכפילים אחד של השני:
- אם אחד מהקולות גדול מ-60 הרץ, הוא נחשב כקול 'גבוה'.
- אם כל ההצבעות הן 60 הרץ או פחות, ההצבעה נחשבת כ'רגילה'.
בנוסף, אם יש שילוב של ערכי קצב פריימים וקטגוריות של קצב פריימים, בדרך כלל הערך הגבוה יותר קובע את קצב הרינדור הסופי. לדוגמה, אם יש שילוב של הצבעה על 60 הרץ והצבעה על 'גבוה', או הצבעה על 120 הרץ והצבעה על 'רגיל', קצב הרינדור בדרך כלל יוגדר ל-120 הרץ.
בנוסף להצבעות מאפליקציה, יכול להיות שיישלחו רמזים אחרים לשכבה ברמה נמוכה יותר מרכיבים שונים באותו פריים. חלק גדול מההתראות האלה מגיע מרכיבי ממשק המשתמש של המערכת, כמו מגש ההתראות, סרגל הסטטוס, סרגל הניווט ועוד. ערכי קצב הפריימים הסופיים נקבעים על סמך ההצבעות מכמה רכיבים.
הגדרת קצב הפריימים או הקטגוריה
בנסיבות מסוימות, יכול להיות שיהיה לכם קצב פריימים מועדף לתצוגה. לדוגמה, אפשר להגדיר את קצב הפריימים המועדף ל'גבוה' בתצוגה כדי להגדיל את קצב הפריימים אם האנימציה לא חלקה. בנוסף, אם יש אנימציה איטית או סטטית מעל סרטון (בדרך כלל מוצגת בקצב של 24 או 30 הרץ), יכול להיות שתעדיפו שהאנימציה תפעל בקצב נמוך מ'רגיל' כדי לצמצם את צריכת החשמל.
אפשר להשתמש בממשקי ה-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 הרץ כברירת מחדל, כי לכל תצוגה מוגדרת 'רגילה' כקצב הפריימים המועדף. עם זאת, יש מקרים חריגים שבהם קצב הפריימים מוגדל ל'גבוה' כדי להבטיח אנימציות חלקות יותר.
המדיניות הכללית בנושא 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 מתאים באופן דינמי את קצב הרענון כשתנועת ההעברה מאטה, ומקטין בהדרגה את קצב הפריימים. כך מתקבל רינדור יעיל יותר, תוך שמירה על גלילה חלקה.
השיפור הזה רלוונטי במיוחד לרכיבי ממשק משתמש שאפשר לגלול בהם, כולל ScrollView
, ListView
ו-GridView
, ויכול להיות שהוא לא יהיה זמין בכל ההטמעות המותאמות אישית.
התכונה 'גלילה של ARR' זמינה ב-RecyclerView
וב-NestedScrollView
. כדי להפעיל את התכונה הזו באפליקציה, צריך לשדרג לגרסאות העדכניות של AndroidX.recyclerview
ושל AndroidX.core
. פרטים נוספים מופיעים בטבלה הבאה.
ספרייה |
גרסה |
|
1.4.0 |
|
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 for Compose
בגרסה 1.9 של Compose נוספה גם תמיכה בקצב רענון דינמי.
במערכת View, משתמשים בשיטה setRequestedFrameRate()
כדי לבקש קצב פריימים ספציפי לתצוגה. ב-Compose, יש משנה חדש שמאפשר להגדיר את קצב הפריימים של רכיב שאפשר להרכיב. המשנה הזה פועל באופן דומה ל-setRequestedFrameRate()
, ומקבל ערך חיובי של קצב פריימים (ב-Hz) או קטגוריה מוגדרת מראש של קצב פריימים, FrameRateCategory
.
החתימות של ממשקי ה-API הן:
Modifier.preferredFrameRate(frameRate: Float)
Modifier.preferredFrameRate(frameRateCategory: FrameRateCategory)
בקטע הקוד הבא, משנה קצב הפריימים החדש (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
)
}
לאחר מכן, קצב הפריימים המועדף מכל הרכיבים הניתנים להרכבה נאסף ומאוחד כדי לקבוע את קצב הפריימים הסופי לכל פריים. פרטים נוספים זמינים במאמרים SetFrameRateSample
וSetFrameRateCategorySample
.