避免未经优化的下载

使用您应用的一些用户在访问互联网时会遇到时断时续的情况,或者他们可以下载到设备上的信息量有限。您可以通过减少您的应用需要下载的数据量来鼓励用户更频繁地与您的应用进行互动。

要减少下载内容,最基本的方法是只下载需要的内容。就数据而言,这意味着实现 REST API,允许您使用上次更新时间等参数来指定限制返回数据的查询条件。

同样,在下载图片时,最好缩减服务器端图片的大小,而不是下载在客户端上缩减的完整尺寸图片。

缓存 HTTP 响应

另一种重要方法是避免下载重复数据。您可以使用缓存降低重复下载同一段数据的可能性。通过缓存应用的数据和资源,您可以针对应用需要引用的信息创建本地副本。如果您的应用需要在短时间内多次访问同一条信息,您只需将其下载到缓存一次即可。

请务必尽量积极缓存,以减少下载的数据总量。请尽可能合理地缓存静态资源,包括按需下载内容(例如完整尺寸图片)。按需资源应分开存储,以便您能够定期清空按需缓存以管理其大小。

为确保缓存不会导致应用显示过时数据,请使用适当的 HTTP 状态代码和标头,例如 ETagLast-Modified 标头。这样,您就可以确定何时应刷新关联内容。例如:

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

您可以将某些网络库配置为自动遵循这些状态代码和标头。例如,使用 OkHttp 时,为客户端配置缓存目录和缓存大小可让库使用 HTTP 缓存,如以下代码示例所示:

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();

配置缓存后,您可以直接从本地存储空间提供完全缓存的 HTTP 请求,无需打开网络连接。有条件缓存的响应可以从服务器验证其新鲜度,从而消除了与下载相关的带宽成本。未缓存的响应会存储在响应缓存中,以响应将来的请求。

您可以使用 Context.getExternalCacheDir() 将非敏感数据缓存到非受管外部缓存目录中。或者,您也可以使用 Context.getCacheDir() 在受管理的安全应用缓存中缓存数据。请注意,当系统可用存储空间不足时,此内部缓存可能会被清空。

使用仓库

如需使用更复杂的缓存方法,请考虑使用仓库设计模式。这涉及创建一个名为“Repository”(存储区)的自定义类,该类针对某些特定数据或资源提供 API 抽象。存储库最初可能会从各种来源(例如远程 Web 服务)提取数据,但在后续调用中会向调用方提供数据的缓存版本。通过这一层间接,您可以提供特定于应用的强大缓存策略。如需详细了解如何在应用中使用仓库模式,请参阅应用架构指南