Niektórzy użytkownicy Twojej aplikacji mają przerywany dostęp do internetu lub limity ilości danych, które mogą pobrać na swoje urządzenia. Możesz zachęcić użytkowników do częstszego korzystania z aplikacji, zmniejszając ilość danych, które musi ona pobrać.
Najprostszym sposobem na zmniejszenie ilości pobieranych danych 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 zapytania ograniczających zwracane dane za pomocą parametrów takich jak czas ostatniej aktualizacji.
Podobnie podczas pobierania obrazów dobrą praktyką jest zmniejszanie ich rozmiaru po stronie serwera, a nie pobieranie obrazów w pełnym rozmiarze i zmniejszanie ich po stronie klienta.
Buforowanie odpowiedzi HTTP
Inną ważną techniką jest unikanie pobierania zduplikowanych danych. Możesz zmniejszyć prawdopodobieństwo wielokrotnego pobierania tych samych danych, korzystając z pamięci podręcznej. Dzięki buforowaniu danych i zasobów aplikacji tworzysz lokalną kopię informacji, do których aplikacja musi się odwoływać. Jeśli aplikacja musi wielokrotnie uzyskać dostęp do tych samych informacji w krótkim czasie, wystarczy, że pobierzesz je do pamięci podręcznej tylko raz.
Ważne jest, aby jak najczęściej korzystać z pamięci podręcznej, aby zmniejszyć łączną ilość pobieranych danych. Zawsze przechowuj w pamięci podręcznej zasoby statyczne, w tym pobierane na żądanie, takie jak obrazy w pełnym rozmiarze, tak długo, jak to możliwe. Zasoby na żądanie powinny być przechowywane oddzielnie, aby można było regularnie czyścić pamięć podręczną na żądanie w celu zarządzania jej rozmiarem.
Aby mieć pewność, że buforowanie nie spowoduje wyświetlania przez aplikację nieaktualnych danych, używaj odpowiednich kodów stanu HTTP i nagłówków, takich jak nagłówki ETag i Last-Modified. Dzięki temu możesz określić, kiedy powiązane treści powinny zostać odświeżone. 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; }
Możesz skonfigurować niektóre biblioteki sieciowe tak, aby automatycznie uwzględniały te kody stanu i nagłówki. Na przykład podczas korzystania z OkHttp skonfigurowanie katalogu i rozmiaru pamięci podręcznej dla klienta umożliwi bibliotece korzystanie z pamięci podręcznej 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 pamięci podręcznej możesz obsługiwać w pełni zapisane w pamięci podręcznej żądania HTTP bezpośrednio z pamięci lokalnej, co eliminuje konieczność otwierania połączenia sieciowego. Odpowiedzi zapisane warunkowo w pamięci podręcznej mogą sprawdzać swoją aktualność na serwerze, co eliminuje koszty przepustowości związane z pobieraniem. Odpowiedzi, które nie są przechowywane w pamięci podręcznej, są zapisywane w pamięci podręcznej odpowiedzi na potrzeby przyszłych żądań.
Możesz zapisać dane, które nie są poufne, w niezarządzanym katalogu zewnętrznej pamięci podręcznej, używając metody Context.getExternalCacheDir().
Możesz też zapisać dane w zarządzanej, bezpiecznej pamięci podręcznej aplikacji za pomocą Context.getCacheDir().
Pamiętaj, że ta wewnętrzna pamięć podręczna może zostać wyczyszczona, gdy w systemie zacznie brakować miejsca na dane.
Używanie repozytorium
Jeśli chcesz zastosować bardziej zaawansowane podejście do buforowania, rozważ wzorzec projektowy repozytorium. Wiąże się to z utworzeniem klasy niestandardowej, znanej jako repozytorium, która zapewnia abstrakcję interfejsu API nad określonymi danymi lub zasobami. Repozytorium może początkowo pobierać dane z różnych źródeł, takich jak zdalna usługa internetowa, ale w kolejnych wywołaniach udostępnia wywołującym wersję danych z pamięci podręcznej. Ta warstwa pośrednia pozwala na stosowanie niezawodnej strategii buforowania, która jest dostosowana do Twojej aplikacji. Więcej informacji o używaniu wzorca repozytorium w aplikacji znajdziesz w Przewodniku po architekturze aplikacji.