Praca z obrazami może szybko powodować problemy z wydajnością, jeśli nie zachowasz ostrożności. Podczas pracy z dużymi bitmapami możesz łatwo napotkać OutOfMemoryError
. Aby zapewnić optymalne działanie aplikacji, postępuj zgodnie z tymi sprawdzonymi metodami.
Wczytywanie tylko potrzebnego rozmiaru mapy bitowej
Większość smartfonów ma aparaty o wysokiej rozdzielczości, które tworzą duże pliki obrazów. Jeśli wyświetlasz obraz na ekranie, musisz zmniejszyć jego rozdzielczość lub załadować go tylko do rozmiaru kontenera obrazu. Ciągłe wczytywanie obrazów większych niż potrzebne może wyczerpać pamięć podręczną GPU, co prowadzi do mniej wydajnego renderowania interfejsu.
Aby zarządzać rozmiarami obrazów:
- Zmniejsz rozmiar plików obrazów do minimum (bez wpływu na obraz wyjściowy).
- Zamiast formatów JPEG lub PNG skonwertuj obrazy do formatu WEBP.
- Dostarczaj mniejsze obrazy dla różnych rozdzielczości ekranu (patrz wskazówka 3).
- Użyj biblioteki wczytywania obrazów, która zmniejsza obraz, aby dopasować go do rozmiaru widoku na ekranie. Może to pomóc zwiększyć wydajność ładowania ekranu.
W miarę możliwości używaj wektorów zamiast bitmap
Gdy chcesz przedstawić coś wizualnie na ekranie, musisz zdecydować, czy można to zrobić za pomocą grafiki wektorowej. Wybieraj obrazy wektorowe zamiast bitmap, ponieważ nie ulegają pikselizacji po przeskalowaniu do różnych rozmiarów. Nie wszystko jednak można przedstawić jako wektor – zdjęć zrobionych aparatem nie można przekonwertować na wektor.
Dostarczanie alternatywnych zasobów dla różnych rozmiarów ekranu
Jeśli wysyłasz obrazy z aplikacją, rozważ dostarczenie zasobów o różnych rozmiarach dla różnych rozdzielczości urządzeń. Może to zmniejszyć rozmiar pliku do pobrania aplikacji na urządzeniach i poprawić wydajność, ponieważ na urządzeniu o niższej rozdzielczości będzie wczytywany obraz o niższej rozdzielczości. Więcej informacji o dostarczaniu alternatywnych bitmap dla różnych rozmiarów urządzeń znajdziesz w dokumentacji dotyczącej alternatywnych bitmap.
Jeśli używasz funkcji ImageBitmap
, przed rysowaniem wywołaj funkcję prepareToDraw
.
Jeśli używasz ImageBitmap
, aby rozpocząć proces przesyłania tekstury do procesora graficznego, przed narysowaniem jej wywołaj funkcję ImageBitmap#prepareToDraw()
. Dzięki temu procesor graficzny może przygotować teksturę i zwiększyć wydajność wyświetlania obrazu na ekranie. Większość bibliotek wczytywania obrazów przeprowadza już tę optymalizację, ale jeśli samodzielnie pracujesz z klasą ImageBitmap
, warto o tym pamiętać.
Zamiast Painter
, w miarę możliwości przekazuj do funkcji kompozycyjnej Int
DrawableRes
lub adres URL jako parametry.
Ze względu na złożoność obsługi obrazów (np. napisanie funkcji „równa się” dla Bitmaps
byłoby kosztowne obliczeniowo) interfejs Painter
nie jest oznaczony jako klasa stabilna. Niestabilne klasy mogą prowadzić do niepotrzebnych ponownych kompozycji, ponieważ kompilator nie może łatwo wywnioskować, czy dane uległy zmianie.
Dlatego lepiej jest przekazywać do funkcji kompozycyjnej adres URL lub identyfikator zasobu rysowalnego jako parametry zamiast przekazywać Painter
jako parametr.
// Prefer this:
@Composable
fun MyImage(url: String) {
}
// Over this:
@Composable
fun MyImage(painter: Painter) {
}
Nie przechowuj mapy bitowej w pamięci dłużej niż jest to konieczne.
Im więcej bitmap załadujesz do pamięci, tym większe jest prawdopodobieństwo, że zabraknie Ci pamięci na urządzeniu. Jeśli na przykład wczytujesz na ekran dużą listę komponentów kompozycyjnych Image, użyj LazyColumn
lub LazyRow
, aby zwolnić pamięć podczas przewijania długiej listy.
Nie pakuj dużych obrazów w pliku AAB/APK.
Jedną z głównych przyczyn dużego rozmiaru pobieranej aplikacji są grafiki spakowane w pliku AAB lub APK. Użyj analizatora APK, aby sprawdzić, czy nie pakujesz większych niż wymagane plików obrazów. Zmniejsz rozmiary lub rozważ umieszczenie obrazów na serwerze i pobieranie ich tylko wtedy, gdy są potrzebne.
Polecane dla Ciebie
- Uwaga: tekst linku jest wyświetlany, gdy JavaScript jest wyłączony.
- ImageBitmap a ImageVector {:#bitmap-vs-vector}
- Zapisywanie stanu interfejsu w Compose
- Etapy Jetpack Compose