ViewCapture to narzędzie programowe, które rejestruje właściwości widoków (takie jak lokalizacja, rozmiar, skala i widoczność) dołączonych do okien, z którymi jest powiązane. ViewCapture rejestruje informacje o różnych widokach w oknie i ich właściwościach, dzięki czemu możesz poznać stan wrażeń użytkownika w określonych momentach i śledzić zmiany w czasie.
Nagrania ekranu mogą wizualizować stan widoku w określonym momencie i pokazywać, jak się zmienia, ale wymagają znacznych zasobów procesora i mogą wpływać na wydajność. Narzędzie ViewCapture ma mniejszy wpływ na zasoby i można je włączać częściej. Dodatkowo ViewCapture wyświetla wizualizacje klatka po klatce na poziomie widoku, co ułatwia sprawdzanie stanu widoku w określonych momentach w porównaniu z nagraniami ekranu.
Na tej stronie dowiesz się, jak wdrożyć ViewCapture w aplikacjach systemowych.
Użyj
ViewCapture.java implementuje instancję onDrawListener i zbiera ślad ViewCapture podczas procesu rysowania. Każde ponowne narysowanie klatki powoduje przejście przez hierarchię drzewa widoków, zaczynając od widoku głównego okna.
Aby zwiększyć wydajność, ViewCapture używa publicznych View.java
metod pobierania do pobierania i kopiowania wartości do
wątku w tle. Implementacja ViewCapture
optymalizuje ten proces, sprawdzając, czy widok jest zmodyfikowany lub unieważniony, za pomocą funkcji captureViewTree,
co pozwala uniknąć przechodzenia przez całą hierarchię widoków. captureViewTree jest dostępna tylko w aplikacjach systemowych i jest częścią interfejsu API UnsupportedAppUsage.
Korzystanie z tego interfejsu API jest ograniczone do aplikacji na podstawie docelowej wersji pakietu SDK.
Ograniczenia
W tej sekcji opisujemy ograniczenia wydajności i pamięci ViewCapture.
Wydajność
Średni narzut wątku głównego na wydajność ViewCapture wynosi 195 μs. W najgorszych przypadkach może to jednak potrwać
około 5 ms. Sprawdź fragment vc#onDraw w
śladzie
Perfetto.
Koszty narzutu wynikają głównie z tych działań:
- Przechodzenie przez hierarchię kosztuje 50 μs, nawet jeśli jest ona przycięta.
- Pobieranie obiektów z alokatora freelist w celu przechowywania kopii właściwości widoku kosztuje 20 μs.
- Pobieranie każdej wartości właściwości za pomocą funkcji pobierającej powoduje wiele dodatkowych wywołań funkcji na widok, co kosztuje 110 μs.
W związku z tym włączenie ViewCapture w trybie śledzenia zawsze włączonego (AOT) negatywnie wpływa na wydajność systemu i powoduje zacinanie się. Ze względu na te ograniczenia wydajności i pamięci to podejście nie jest gotowe do AOT. Zalecamy używanie ViewCapture tylko do debugowania w laboratorium i lokalnego.
Pamięć
Metoda Perfetto do śladów ViewCapture używa pojedynczego bufora pierścieniowego o predefiniowanym rozmiarze, aby zapobiec nadmiernemu wykorzystaniu pamięci. To podejście zapobiega nadmiernemu zużyciu pamięci, ponieważ nie używa oddzielnych buforów pierścieniowych dla każdego okna. Nie rozwiązuje to jednak problemu przechowywania całej hierarchii widoków dla każdego stanu w Perfetto dla każdej klatki. Nagrywanie pojedynczego okna, np. NexusLauncher, może wygenerować ponad 30 sekund danych ViewCapture w buforze o rozmiarze 10 MB. Rejestrowanie ponad 30 okien z interfejsu systemowego wymaga większego bufora lub znacznie krótszego czasu nagrywania.
Instrukcje
Aby wdrożyć ViewCapture w aplikacjach systemowych, wykonaj te czynności:
Dodaj zależność do pliku
Android.bp, jak pokazano w kodzie Launchera.android_library { name: "YourLib", static_libs: [ ... "//frameworks/libs/systemui:view_capture", ... ], platform_apis: true, privileged: true, }Podczas tworzenia okna utwórz instancję ViewCapture, na przykład:
-
private SafeCloseable mViewCapture; @Override protected void onCreate(Bundle savedInstanceState) { ... mViewCapture = ViewCaptureFactory.getInstance(this).startCapture(getWindow()); } -
private SafeCloseable mViewCapture; @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); if (enableViewCaptureTracing()) { mViewCaptureCloseable = ViewCaptureFactory.getInstance(getContext()) .startCapture(getRootView(), ".NotificationShadeWindowView"); } ... }
-
Po zniszczeniu okna zamknij instancję ViewCapture, jak pokazano w tych przykładach:
-
@Override public void onDestroy() { ... if (mViewCapture != null) mViewCapture.close(); } -
@Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); if (mViewCaptureCloseable != null) { mViewCaptureCloseable.close(); } ... }
-