Unikaj pobierania niezoptymalizowanych plików

Niektórzy użytkownicy Twojej aplikacji mają ograniczony dostęp do internetu lub są ograniczone ilości informacji, które mogą pobrać na swoje urządzenia. Możesz zachęcić użytkowników do częstszego korzystania z aplikacji, ograniczając ilość danych, które musi ona pobrać.

Najważniejszym sposobem na zmniejszenie liczby pobrań jest pobieranie tylko tego, czego potrzebujesz. W przypadku danych oznacza to wdrożenie interfejsów API typu REST, które umożliwiają określenie kryteriów zapytań ograniczających zwracane dane za pomocą parametrów takich jak czas ostatniej aktualizacji.

Podobnie w przypadku pobierania obrazów warto zmniejszyć ich rozmiar po stronie serwera zamiast pobierać obrazy w pełnym rozmiarze, które są pomniejszone po stronie klienta.

Buforuj odpowiedzi HTTP

Inną ważną metodą jest unikanie pobierania zduplikowanych danych. Możesz zmniejszyć prawdopodobieństwo wielokrotnego pobierania tych samych danych, używając pamięci podręcznej. Zapisując dane i zasoby aplikacji w pamięci podręcznej, tworzysz lokalną kopię informacji, do których aplikacja ma się odwoływać. Jeśli aplikacja musi wielokrotnie uzyskać dostęp do tych samych informacji w krótkim czasie, wystarczy, że pobierze ją do pamięci podręcznej tylko raz.

Aby zmniejszyć łączną ilość pobieranych danych, musisz maksymalnie zapisywać pamięć podręczną. Zawsze zapisuj w pamięci podręcznej zasoby statyczne, w tym pliki do pobrania na żądanie, takie jak obrazy w pełnym rozmiarze, tak długo, jak to możliwe. Zasoby na żądanie powinny być przechowywane oddzielnie, aby umożliwić regularne opróżnianie pamięci podręcznej na żądanie w celu zarządzania jej rozmiarem.

Aby mieć pewność, że buforowanie nie powoduje wyświetlania w aplikacji nieaktualnych danych, używaj odpowiednich kodów stanu i nagłówków HTTP, np. nagłówków ETag i Last-Modified. Dzięki temu możesz określić, kiedy powiązana treść ma być odświeżana. Na przykład:

Kotlin

// url represents the website containing the content to place into the cache.
val conn: HttpsURLConnection = url.openConnection() as HttpsURLConnection
val currentTime: Long = System.currentTimeMillis()
val lastModified: Long = conn.getHeaderFieldDate("Last-Modified", currentTime)

// lastUpdateTime represents when the cache was last updated.
if (lastModified < lastUpdateTime) {
    // Skip update
} else {
    // Parse update
    lastUpdateTime = lastModified
}

Java

// url represents the website containing the content to place into the cache.
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
long currentTime = System.currentTimeMillis();
long lastModified = conn.getHeaderFieldDate("Last-Modified", currentTime);

// lastUpdateTime represents when the cache was last updated.
if (lastModified < lastUpdateTime) {
    // Skip update
} else {
    // Parse update
    lastUpdateTime = lastModified;
}

Niektóre biblioteki sieci możesz skonfigurować tak, aby automatycznie respektowały te kody stanu i nagłówki. Jeśli na przykład używasz OkHttp, skonfigurowanie katalogu pamięci podręcznej klienta i rozmiaru pamięci podręcznej spowoduje, że biblioteka będzie mogła korzystać z buforowania HTTP, jak pokazano w tym przykładowym kodzie:

Kotlin

val cacheDir = Context.getCacheDir()
val cacheSize = 10L * 1024L * 1024L // 10 MiB
val client: OkHttpClient = OkHttpClient.Builder()
    .cache(Cache(cacheDir, cacheSize))
    .build()

Java

File cacheDir = Context.getCacheDir();
long cacheSize = 10L * 1024L * 1024L; // 10 MiB
OkHttpClient client = new OkHttpClient.Builder()
    .cache(new Cache(cacheDir, cacheSize))
    .build();

Po skonfigurowaniu tej pamięci podręcznej możesz obsługiwać żądania HTTP w pełni zapisane w pamięci podręcznej bezpośrednio z pamięci lokalnej, eliminując potrzebę nawiązywania połączenia sieciowego. Warunkowo przechowywane odpowiedzi mogą sprawdzać aktualność na serwerze, co eliminuje koszty przepustowości związane z pobieraniem. Odpowiedzi niebuforowane są przechowywane w pamięci podręcznej odpowiedzi na potrzeby przyszłych żądań.

Możesz buforować niewrażliwe dane w niezarządzanym katalogu zewnętrznej pamięci podręcznej, używając Context.getExternalCacheDir(). Możesz też buforować dane w bezpiecznej pamięci podręcznej zarządzanej, bezpiecznej aplikacji za pomocą metody Context.getCacheDir(). Pamiętaj, że wewnętrzna pamięć podręczna może zostać opróżniona, gdy w systemie zacznie brakować dostępnej pamięci.

Użyj repozytorium

Bardziej zaawansowane podejście do buforowania jest możliwe dzięki schematowi projektowemu repozytorium. Wymaga to utworzenia klasy niestandardowej zwanej repozytorium, która zapewnia abstrakcję przez interfejs API w przypadku określonych danych lub zasobów. Repozytorium może początkowo pobierać dane z różnych źródeł, takich jak zdalna usługa internetowa, ale udostępnia obiektom wywołującym wersję danych z pamięci podręcznej w kolejnych wywołaniach. Ta warstwa pośrednia pozwala stworzyć solidną strategię buforowania zgodną z Twoją aplikacją. Więcej informacji o używaniu wzorca repozytorium w aplikacji znajdziesz w przewodniku po architekturze aplikacji.