Optymalizacja skuteczności obrazów

Jeśli nie będziesz uważać, praca z obrazami może szybko spowodować problemy z wydajnością. Podczas pracy z dużymi mapami bitowymi łatwo natrafisz na obiekt OutOfMemoryError. Aby Twoja aplikacja działała jak najlepiej, stosuj te sprawdzone metody.

Ładuj tylko potrzebny rozmiar bitmapy

Większość smartfonów ma aparaty o wysokiej rozdzielczości, które generują duże pliki graficzne. Jeśli wyświetlasz obraz na ekranie, musisz zmniejszyć jego rozdzielczość lub załadować obraz tylko do rozmiaru kontenera. Ciągłe ładowanie większych, niż jest to potrzebne, może powodować wyczerpywanie pamięci podręcznej GPU, co prowadzi do mniej wydajnego renderowania UI.

Aby zarządzać rozmiarami obrazów:

  • Zmniejsz rozmiar plików obrazów do możliwie najmniejszego (bez wpływu na obraz wyjściowy).
  • Rozważ konwersję obrazów na format WebP zamiast na formaty JPEG czy PNG.
  • Prześlij mniejsze obrazy w przypadku różnych rozdzielczości ekranu (patrz wskazówka 3),
  • Użyj biblioteki wczytywania obrazów, która zmniejsza obraz, aby pasował do rozmiaru widoku na ekranie. Może to poprawić wydajność wczytywania ekranu.

W miarę możliwości używaj wektorów zamiast bitmap.

Podczas reprezentowania czegoś na ekranie musisz zdecydować, czy może to być wektor. Zamiast bitmap stosuj obrazy wektorowe, ponieważ nie stają się one pikselowe, gdy przeskalujesz je do różnych rozmiarów. Jednak nie wszystko da się przedstawić w postaci wektora – zdjęć zrobionych aparatem nie da się przekształcić w wektory.

Przesyłanie zasobów alternatywnych na potrzeby różnych rozmiarów ekranu

Jeśli przesyłasz obrazy wraz z aplikacją, rozważ dostarczenie zasobów o różnych rozmiarach na potrzeby różnych rozdzielczości urządzeń. Pomoże to zmniejszyć rozmiar pliku do pobrania aplikacji na urządzeniach i poprawić wydajność, ponieważ na urządzeniu o niższej rozdzielczości wczytywane będą obrazy o niższej rozdzielczości. Więcej informacji o zapewnianiu bitmap alternatywnych na potrzeby różnych rozmiarów urządzeń znajdziesz w dokumentacji bitmap alternatywnych.

Jeśli używasz ImageBitmap, przed narysowaniem użyj funkcji prepareToDraw.

Jeśli używasz funkcji ImageBitmap, przed rozpoczęciem przesyłania tekstury do karty graficznej wywołaj funkcję ImageBitmap#prepareToDraw(), zanim ją narysujesz. Pomaga to procesorowi graficznemu przygotować teksturę i poprawić wydajność wyświetlania elementów wizualnych na ekranie. Większość bibliotek do ładowania obrazów już stosuje tę optymalizację, ale jeśli pracujesz z klasą ImageBitmap, musisz o tym pamiętać.

Wolisz przekazywać do obiektu kompozycyjnego Int DrawableRes lub URL jako parametry zamiast Painter

Ze względu na złożoność obsługi obrazów (np. napisanie funkcji równania dla Bitmaps byłoby kosztowne pod względem obliczeniowym) interfejs API Painter nie jest wyraźnie oznaczony jako klasa stabilna. Niestabilne klasy mogą prowadzić do niepotrzebnych zmian, ponieważ kompilator nie jest w stanie łatwo wywnioskować, czy dane uległy zmianie.

Dlatego lepiej jest przekazać URL lub identyfikator zasobu rysowanego jako parametry do kompozytowego, zamiast przekazywać parametr Painter.

// Prefer this:
@Composable
fun MyImage(url: String) {

}
// Over this:
@Composable
fun MyImage(painter: Painter) {

}

Nie przechowuj bitmapy w pamięci dłużej, niż jest to konieczne

Im więcej map bitowych wczytasz w pamięci, tym większe prawdopodobieństwo, że zabraknie pamięci na urządzeniu. Jeśli na przykład wczytujesz na ekranie dużą listę komponentów ImageComposables, użyj opcji LazyColumn lub LazyRow, aby zapewnić zwolnienie pamięci podczas przewijania dużej listy.

Nie pakuj dużych obrazów w pliku AAB lub APK

Jedną z najczęstszych przyczyn dużego rozmiaru pobieranej aplikacji jest grafika spakowana w pliku AAB lub APK. Użyj narzędzia analizatora pliku APK, aby sprawdzić, czy nie pakujesz plików obrazów większych niż wymagane. Zmniejsz rozmiary lub rozważ umieszczenie obrazów na serwerze i pobieranie ich tylko wtedy, gdy jest to konieczne.