2013-03-21 16 views
17

TL; DR: Ponieważ getDrawingCache() wydaje się wywoływać przerysowanie od View, gdy akceleracja sprzętowa jest włączona, czy istnieje alternatywny sposób uzyskania Bitmap (lub czegoś podobnego), które to unika, być może przez odczytanie danych w (sprzęt, oprogramowanie), kiedy ostatni raz rysowano View?Efektywne "Zrzuty ekranu" widoku?


Niektóre tła:

Android miał możliwość lusterka ekran od Androida 3.0, takie jak na załączonym wyświetlaczem HDMI. Może to być wykorzystane do prezentacji, ale oznacza to, że widzowie widzą to samo, co prezenter, co nie zawsze jest idealne.

Android 4.2 dodano Presentation, aby umożliwić aplikacjom umieszczanie dowolnych rzeczy na "drugim ekranie" (np. Podłączonym wyświetlaczu HDMI). W tym przypadku czasami przydatne byłoby wyświetlenie na drugim ekranie części ekranu widocznej na wyświetlaczu głównego tabletu. Jeśli myślisz o oprogramowaniu do prezentacji, takim jak Microsoft PowerPoint, LibreOffice Impress i tym podobne, w typowych konfiguracjach z dwoma ekranami, publiczność zobaczy bieżący slajd prezentacji, a prezenter zobaczy bieżący slajd oraz zegar i notatki prelegenta oraz ...

Dla treści nieinteraktywnych, takich jak PNG reprezentujący slajd, jest to po prostu kwestia pokazania tego samego obrazu na obu ekranach (obok innych rzeczy na ekranie głównym).

Jednak w przypadku treści interaktywnych, takich jak WebView, czasami trudno jest wykonać takie odzwierciedlenie. Na przykład, nie mamy dobrego sposobu na sprawdzenie, czy zawartość WebView może ulec zmianie, ponieważ może to zrobić w oparciu o rzeczy czysto wewnątrz samego siebie (na przykład kończenie połączeń AJAX), a nie o czymś, co robimy oddzielnie. I nawet jeśli my zrobiliśmy, gdy zmieniła się zawartość WebView, nie mamy dobrego sposobu na uzyskanie innej WebView, aby renderować tę samą zawartość.

więc pomyślałem, że spróbuję założyć MirroringFrameLayout, że użyłby getDrawingCache() aby pobrać Bitmap zawartości kontenera i dostarczamy że do kogoś, kto może uczynić go na ekranie (np ImageView przedstawionym w Presentation).

Jednak z akceleracji sprzętowej włączeniu setDrawingCacheEnabled(true)is somewhat of a no-op:

Włączanie cache rysunek jest podobny do ustawiania warstwę gdy przyspieszenie sprzętowe jest wyłączone. Gdy akceleracja sprzętowa jest włączona, włączenie buforowania rysunku nie ma wpływu na renderowanie, ponieważ system używa innego mechanizmu przyspieszania, który ignoruje flagę.

Wywołanie getDrawingCache() w tych przypadkach wymusza pełną draw() z View na bitmapę-backed Canvas, zamiast faktycznie przy użyciu pamięci podręcznej. Ponieważ draw() może być kosztowne, wykonywanie draw() często (powiedzmy, wyzwalane przez postOnAnimation()) powoduje jank.

Dlatego próbuję ustalić, czy istnieje jakaś inna "pamięć podręczna rysowania", wykraczająca poza getDrawingCache(), której możemy użyć z włączonym przyspieszeniem sprzętowym, które może być użyte do skonfigurowania tego lustrzanego odbicia, a to jest bardziej wydajne.Z tego, co widzę, nie ma takiej pamięci podręcznej, ponieważ warstwy są skutecznie napisane tylko z punktu widzenia aplikacji SDK. Mam jednak nadzieję, że być może brakuje mi jakiegoś rozwiązania.

Z góry dziękuję!

+0

FYI, oto repozytorium GitHub zawierające moją implementację: https://github.com/commonsguy/cwac-layouts – CommonsWare

Odpowiedz

13

Możesz użyć setLayerType(View.LAYER_TYPE_SOFTWARE, null), ale efekt uboczny spowoduje spowolnienie tego widoku do przerysowania za każdym razem, gdy zostanie zaktualizowany. O wiele bardziej wydajne byłoby stworzenie niestandardowego ViewGroup, który narysowałby Twój widok na dwóch płótnie (po jednym na każdy ekran). Można również po prostu użyć ViewTreeObserver, a przy każdym wywołaniu zwrotnym zmusić twój widok do renderowania na drugim ekranie. Naprawdę zalecam, aby nie próbować nadużywać pamięci podręcznej/typu rysunku dla takich przypadków użycia.

+0

Czy można bezpiecznie renderować do osobnego 'Canvas' z' onDraw() 'w niestandardowym 'ViewGroup'? – CommonsWare

+0

Tak długo, jak z wątku interfejsu użytkownika, tak. –

+0

OK, jak na razie wygląda na to, że działa. Następny projekt: prawidłowe skalowanie, ponieważ rozmiar lustra może nie być identyczny z rozmiarem oryginału. Aby zacytować stronę szkoleniową "Powiększanie widoku", "Yay, matematyka". :-) Dzięki! – CommonsWare

Powiązane problemy