Nicht optimierte Downloads vermeiden

Einige Nutzer deiner App haben nur zeitweise Zugriff auf das Internet oder können nur eine begrenzte Menge an Informationen auf ihre Geräte herunterladen. Sie können Nutzer dazu ermutigen, häufiger mit Ihrer App zu interagieren, indem Sie die Datenmenge reduzieren, die Ihre App herunterladen muss.

Die grundlegendste Methode, um die Anzahl der Downloads zu reduzieren, besteht darin, nur das herunterzuladen, was Sie benötigen. In Bezug auf Daten bedeutet dies, dass REST APIs implementiert werden, mit denen Sie Abfragekriterien angeben können, die die zurückgegebenen Daten mithilfe von Parametern wie dem Zeitpunkt der letzten Aktualisierung einschränken.

Ebenso empfiehlt es sich, beim Herunterladen von Bildern die Größe der Bilder serverseitig zu reduzieren, anstatt Bilder in voller Größe herunterzuladen, die dann auf dem Client verkleinert werden.

HTTP-Antworten im Cache speichern

Eine weitere wichtige Technik ist das Vermeiden des Herunterladens doppelter Daten. Durch Caching können Sie die Wahrscheinlichkeit verringern, dass dieselben Daten wiederholt heruntergeladen werden. Durch das Caching der Daten und Ressourcen Ihrer App erstellen Sie eine lokale Kopie der Informationen, auf die Ihre App verweisen muss. Wenn Ihre App innerhalb eines kurzen Zeitraums mehrmals auf dieselben Informationen zugreifen muss, müssen Sie sie nur einmal in den Cache herunterladen.

Es ist wichtig, so aggressiv wie möglich zu cachen, um die Gesamtmenge der heruntergeladenen Daten zu reduzieren. Statische Ressourcen, einschließlich On-Demand-Downloads wie Bilder in voller Größe, sollten immer so lange wie möglich im Cache gespeichert werden. On-Demand-Ressourcen sollten separat gespeichert werden, damit Sie den On-Demand-Cache regelmäßig leeren können, um seine Größe zu verwalten.

Damit Ihre Anwendung durch das Caching keine veralteten Daten anzeigt, verwenden Sie die entsprechenden HTTP-Statuscodes und -Header, z. B. die Header ETag und Last-Modified. So können Sie festlegen, wann die zugehörigen Inhalte aktualisiert werden sollen. Beispiel:

// 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
}

Sie können einige Netzwerkbibliotheken so konfigurieren, dass diese Statuscodes und Header automatisch berücksichtigt werden. Wenn Sie beispielsweise OkHttp verwenden, können Sie ein Cache-Verzeichnis und eine Cache-Größe für den Client konfigurieren, damit die Bibliothek HTTP-Caching verwenden kann, wie im folgenden Codebeispiel gezeigt:

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

Wenn der Cache konfiguriert ist, können Sie vollständig im Cache gespeicherte HTTP-Anfragen direkt aus dem lokalen Speicher bereitstellen, sodass keine Netzwerkverbindung geöffnet werden muss. Bei bedingt im Cache gespeicherten Antworten kann die Aktualität vom Server validiert werden, sodass die mit dem Download verbundenen Bandbreitenkosten entfallen. Nicht im Cache gespeicherte Antworten werden für zukünftige Anfragen im Antwort-Cache gespeichert.

Sie können nicht vertrauliche Daten im nicht verwalteten externen Cache-Verzeichnis mit Context.getExternalCacheDir() im Cache speichern. Alternativ können Sie Daten im verwalteten, sicheren Anwendungscache mit Context.getCacheDir() im Cache speichern. Dieser interne Cache wird möglicherweise geleert, wenn der verfügbare Speicherplatz knapp wird.

Repository verwenden

Wenn Sie einen komplexeren Ansatz für das Caching benötigen, sollten Sie das Repository-Entwurfsmuster in Betracht ziehen. Dazu wird eine benutzerdefinierte Klasse erstellt, die als Repository bezeichnet wird und eine API-Abstraktion für bestimmte Daten oder Ressourcen bereitstellt. Das Repository kann seine Daten anfangs aus verschiedenen Quellen abrufen, z. B. von einem Remote-Webdienst, stellt Aufrufern aber bei nachfolgenden Aufrufen eine im Cache gespeicherte Version der Daten zur Verfügung. Diese Indirektionsebene ermöglicht es Ihnen, eine robuste Caching-Strategie bereitzustellen, die speziell auf Ihre App zugeschnitten ist. Weitere Informationen zur Verwendung des Repository-Musters in Ihrer App finden Sie im Leitfaden zur App-Architektur.