Gdy w Androidzie rozpoczyna się animacja, wyświetlacz często zwiększa częstotliwość odświeżania do maksymalnej wartości, aby zapewnić płynność działania. W przypadku małych animacji, takich jak paski postępu i wizualizatory dźwięku, wysoka częstotliwość odświeżania jest niepotrzebna i powoduje wysokie zużycie energii.
Od Androida 15 urządzenia z włączoną funkcją adaptacyjnej częstotliwości odświeżania (ARR) mogą zmniejszać czas działania z wysoką częstotliwością odświeżania na 2 sposoby:
- Dzięki nowym optymalizacjom zarządzania liczbą klatek na platformie aplikacje mogą domyślnie renderować obraz z mniejszą liczbą klatek i zwiększać ją tylko wtedy, gdy jest to konieczne.
- Częstotliwość odświeżania wyświetlacza jest dynamicznie dopasowywana do częstotliwości renderowania treści bez zacinania się.
Większość aplikacji powinna korzystać z ARR bez żadnych modyfikacji, ale w razie potrzeby możesz też zastąpić domyślne działanie dotyczące liczby klatek na sekundę.
Na tej stronie znajdziesz informacje na te tematy:
- Sposób określania liczby klatek na sekundę w każdym widoku.
- Ogólne zasady określające, jak ARR ustala szybkość klatek.
- Jak ręcznie zastąpić domyślne działanie liczby klatek.
Mechanizm głosowania w widoku
W systemie widoków Androida każdy widok w hierarchii interfejsu może określać preferowaną liczbę klatek na sekundę. Te preferencje są zbierane i łączone w celu określenia ostatecznej liczby klatek na sekundę dla każdej klatki. Jest to realizowane za pomocą mechanizmu głosowania, w którym każdy widok głosuje na podstawie atrybutu liczby klatek na sekundę, który może być kategorią lub konkretną wartością. Widoki zwykle głosują po narysowaniu lub zaktualizowaniu. Głosy te są łączone w celu określenia ostatecznej liczby klatek na sekundę, która jest następnie wysyłana do warstwy niższego poziomu jako wskazówka dotycząca renderowania.
Obecnie większość widoków ma domyślną częstotliwość odświeżania „Normal”, która jest często ustawiona na 60 Hz. W przypadku wyższych częstotliwości odświeżania możesz używać określonych interfejsów API do dostosowywania preferencji, przy czym system zwykle wybiera najwyższą częstotliwość odświeżania. Więcej informacji o korzystaniu z tych interfejsów API znajdziesz w sekcji Ustawianie liczby klatek na sekundę lub kategorii. Ogólne zasady dotyczące liczby klatek na sekundę są opisane w sekcji Ogólne zasady ARR.
Kategorie liczby klatek
W klasie View
są różne kategorie liczby klatek na sekundę, które można wykorzystać w głosowaniu. Opis każdej kategorii znajdziesz poniżej:
REQUESTED_FRAME_RATE_CATEGORY_DEFAULT
: tę wartość można ustawić, aby przywrócić działanie domyślne, co oznacza, że ten widok nie zawiera danych o liczbie klatek na sekundę.REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE
: widok nie będzie miał wpływu na liczbę klatek na sekundę. Oznacza to, że nawet jeśli widok jest aktywny, platforma nie będzie go uwzględniać podczas określania liczby klatek na sekundę.REQUESTED_FRAME_RATE_CATEGORY_NORMAL
: oznacza średnią liczbę klatek na sekundę, która jest odpowiednia w przypadku animacji, które nie wymagają większej liczby klatek na sekundę ani nie zyskują na większej płynności. Zwykle jest to 60 Hz lub wartość zbliżona.REQUESTED_FRAME_RATE_CATEGORY_HIGH
: oznacza liczbę klatek odpowiednią dla animacji, które wymagają dużej liczby klatek na sekundę. Może to zwiększyć płynność, ale też zużycie energii.
Widok głosuje tylko wtedy, gdy wymaga ponownego narysowania. Ostateczna liczba klatek na sekundę jest określana na podstawie największej liczby głosów. Jeśli na przykład wszystkie głosy są oddane na „Normalny”, wybierana jest opcja „Normalny”. Jeśli pojawią się głosy „Normalny” i „Wysoki”, wybierany jest „Wysoki”.
Liczba klatek
Oprócz kategorii liczby klatek widok może też określać preferowaną liczbę klatek, np. 30, 60 lub 120 Hz. Jeśli oddanych zostanie kilka głosów dotyczących liczby klatek, ostateczna liczba klatek zostanie określona zgodnie z tymi regułami:
- Wielokrotności: jeśli głosowane liczby klatek na sekundę są wielokrotnościami siebie nawzajem, wybierana jest najwyższa wartość. Jeśli na przykład są 2 głosy – 30 Hz i 90 Hz – jako końcowa liczba klatek na sekundę zostanie wybrana wartość 90 Hz.
- Nie są wielokrotnościami siebie nawzajem:
- Jeśli którykolwiek z głosów jest większy niż 60 Hz, jest on uznawany za głos „Wysoki”.
- Jeśli wszystkie głosy mają wartość 60 Hz lub niższą, liczą się jako głos „Normalny”.
Jeśli występują zarówno wartości liczby klatek, jak i kategorie liczby klatek, wyższa wartość zwykle określa ostateczną liczbę klatek. Na przykład w przypadku połączenia głosowania z częstotliwością 60 Hz i głosowania „Wysoka” lub głosowania z częstotliwością 120 Hz i głosowania „Normalna” częstotliwość renderowania jest zwykle ustawiana na 120 Hz.
Oprócz głosów z aplikacji mogą być też wysyłane inne wskazówki do warstwy niższego poziomu z różnych komponentów w tej samej ramce. Wiele z nich może pochodzić z komponentów interfejsu systemu, takich jak panel powiadomień, pasek stanu, pasek nawigacyjny i inne. Ostateczne wartości liczby klatek na sekundę są określane na podstawie głosów z wielu komponentów.
Ustaw liczbę klatek lub kategorię
W określonych okolicznościach możesz mieć preferowaną liczbę klatek dla widoku. Możesz na przykład ustawić preferowaną liczbę klatek na „Wysoka” w przypadku widoku, aby zwiększyć liczbę klatek, jeśli animacja wydaje się mało płynna. Jeśli na filmie jest wyświetlana powolna lub statyczna animacja (zwykle odtwarzana z częstotliwością 24 lub 30 Hz), możesz ustawić jej szybkość na niższą niż „Normalna”, aby zmniejszyć zużycie energii.
Za pomocą interfejsów API setRequestedFrameRate()
i getRequestedFrameRate()
możesz określić preferowaną liczbę klatek na sekundę lub kategorię danego widoku.
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);
Przykłady użycia znajdziesz w sekcji TextureView
.
Ogólne zasady ARR
W poprzedniej sekcji wspomnieliśmy, że większość animacji jest domyślnie wyświetlana z częstotliwością 60 Hz, ponieważ każdy widok ma ustawioną preferowaną częstotliwość klatek na „Normal”. Istnieją jednak wyjątki, w których liczba klatek jest zwiększana do „Wysokiej”, aby zapewnić płynniejsze animacje.
Ogólne zasady dotyczące ARR są następujące:
- Wzmocnienie dotyku: gdy zostanie wykryte zdarzenie dotyku (
MotionEvent.ACTION_DOWN
), częstotliwość odświeżania jest zwiększana do „Wysokiej” na pewien czas po zwolnieniu dotyku, aby zachować responsywność. - Gesty szybkiego przesunięcia: gesty szybkiego przesunięcia są obsługiwane inaczej – częstotliwość odświeżania stopniowo maleje wraz ze zmniejszaniem się prędkości przesunięcia. Szczegółowe informacje o tym działaniu znajdziesz w sekcji Ulepszone przewijanie.
- Uruchamianie aplikacji i przejścia między oknami: częstotliwość odświeżania jest też zwiększana na pewien czas podczas uruchamiania aplikacji, inicjowania okien i przejść między oknami, aby zapewnić płynne wrażenia wizualne.
- Animacje: animacje, które obejmują ruch lub zmiany rozmiaru, automatycznie otrzymują wyższą częstotliwość odświeżania, aby zwiększyć płynność, gdy zmienia się pozycja lub rozmiar widoku.
SurfaceView
iTextureView
: liczba klatek ustawiona wyraźnie dlaTextureView
iSurfaceView
jest respektowana i odpowiednio stosowana.
Włączanie i wyłączanie wzmocnienia dotyku
Wzmocnienie dotyku możesz włączyć lub wyłączyć na poziomie Window
. Domyślnie, gdy użytkownik dotknie ekranu i odsunie od niego palec, częstotliwość renderowania na jakiś czas wzrasta. Interfejsy setFrameRateBoostOnTouchEnabled()
i getFrameRateBoostOnTouchEnabled()
umożliwiają zapobieganie zwiększaniu częstotliwości renderowania, gdy dotknięty zostanie określony 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()
Ulepszone przewijanie
Jednym z głównych zastosowań dynamicznej optymalizacji liczby klatek jest poprawa przewijania (szybkiego przewijania). Wiele aplikacji w dużym stopniu zależy od tego, czy użytkownicy przesuwają palcem w górę, aby wyświetlić nowe treści. Ulepszenie przewijania ARR dynamicznie dostosowuje częstotliwość odświeżania w miarę zwalniania gestu machnięcia, stopniowo zmniejszając liczbę klatek na sekundę. Zapewnia to wydajniejsze renderowanie przy zachowaniu płynnego przewijania.
To ulepszenie dotyczy w szczególności komponentów interfejsu, które można przewijać, w tym ScrollView
, ListView
i GridView
, i może nie być dostępne we wszystkich implementacjach niestandardowych.
Funkcja przewijania ARR jest dostępna w przypadku dostawców RecyclerView
i NestedScrollView
. Aby włączyć tę funkcję w aplikacji, przejdź na najnowsze wersje AndroidX.recyclerview
i AndroidX.core
. Szczegółowe informacje znajdziesz w tabeli poniżej.
Biblioteka |
Wersja |
|
1.4.0 |
|
1.15.0 |
Ustawianie informacji o prędkości
Jeśli masz niestandardowy komponent z możliwością przewijania i chcesz korzystać z funkcji przewijania, wywołuj setFrameContentVelocity()
w każdej klatce podczas płynnego przewijania lub szybkiego przewijania. Przykład znajdziesz w tym fragmencie kodu:
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()
Więcej przykładów znajdziesz w sekcjach RecyclerView
i ScrollView
. Aby prawidłowo ustawić prędkość, oblicz prędkość treści (piksele na sekundę) ręcznie, jeśli wymaganych informacji nie można uzyskać z Scroller
lub OverScroller
.
Pamiętaj, że jeśli funkcje setFrameContentVelocity()
i getFrameContentVelocity()
zostaną wywołane w przypadku widoków, które nie są komponentami z możliwością przewijania, nie będą miały żadnego wpływu, ponieważ ruch automatycznie wywołuje zwiększoną liczbę klatek na sekundę na podstawie bieżącej zasady.
Informacje o prędkości są kluczowe do dostosowania szybkości renderowania. Weźmy na przykład gest szybkiego przesunięcia. Na początku szybkość rzutu może być duża, co wymaga wyższego współczynnika renderowania, aby zapewnić płynność. W miarę wykonywania gestu prędkość maleje, co pozwala obniżyć częstotliwość renderowania.
Włączanie i wyłączanie ARR
Funkcja ARR jest domyślnie włączona, aby zwiększyć efektywność energetyczną. Możesz wyłączyć tę funkcję, ale nie jest to zalecane, ponieważ aplikacja będzie zużywać więcej energii. Wyłącz tę funkcję tylko wtedy, gdy napotkasz problemy, które znacząco wpływają na wrażenia użytkowników.
Aby włączyć lub wyłączyć ARR, użyj interfejsu API setFrameRatePowerSavingsBalanced()
na Window
lub interfejsu API isFrameRatePowerSavingsBalanced()
w pliku styles.xml
.
Poniższy fragment kodu pokazuje, jak włączyć lub wyłączyć ARR w przypadku 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()
Aby wyłączyć ARR w pliku styles.xml
, dodaj do stylu w pliku res/values/styles.xml
ten element:
<style name="frameRatePowerSavingsBalancedDisabled">
<item name="android:windowIsFrameRatePowerSavingsBalanced">false</item>
</style>
Roczne powtarzające się przychody z usługi Compose
Compose 1.9 obsługuje też adaptacyjną częstotliwość odświeżania.
W systemie View używasz metody setRequestedFrameRate()
, aby poprosić o określoną liczbę klatek na sekundę dla widoku. W Compose nowy modyfikator umożliwia określenie liczby klatek na sekundę dla komponentu. Ten modyfikator działa podobnie do setRequestedFrameRate()
. Może przyjmować dodatnią wartość liczby klatek na sekundę (w Hz) lub zdefiniowaną kategorię liczby klatek na sekundę, FrameRateCategory
.
Sygnatury interfejsów API są takie:
Modifier.preferredFrameRate(frameRate: Float)
Modifier.preferredFrameRate(frameRateCategory: FrameRateCategory)
W poniższym fragmencie kodu nowy modyfikator liczby klatek (Modifier.requestedFrameRate(120f))
jest stosowany do funkcji kompozycyjnej Text
. Ten modyfikator powoduje, że funkcja kompozycyjna Text
podczas rysowania lub animowania (np. przy zmianach krycia) żąda preferowanej liczby klatek wynoszącej 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
)
}
Preferowane liczby klatek ze wszystkich komponentów są następnie zbierane i łączone, aby określić ostateczną liczbę klatek dla każdej klatki. Więcej informacji znajdziesz w sekcjach SetFrameRateSample
i SetFrameRateCategorySample
.