为啥对 HttpResponseCache 使用反射?

Posted

技术标签:

【中文标题】为啥对 HttpResponseCache 使用反射?【英文标题】:Why use reflection for HttpResponseCache?为什么对 HttpResponseCache 使用反射? 【发布时间】:2014-06-08 09:49:36 【问题描述】:

HttpResponseCache 的documentation 中有一段:

使用早期版本

这个类是在 android 4.0 (Ice Cream Sandwich) 中添加的。采用 反射以启用响应缓存而不影响早期 发布:

try 
    File httpCacheDir = new File(context.getCacheDir(), "http");
    long httpCacheSize = 10 * 1024 * 1024; // 10 MiB
    Class.forName("android.net.http.HttpResponseCache")
        .getMethod("install", File.class, long.class)
        .invoke(null, httpCacheDir, httpCacheSize);

catch (Exception httpResponseCacheNotAvailable) 

您可以在关于 SO(例如here)的问题和网络上的示例中通过反射查看此调用。我还接管了包含这个确切 sn-p 的代码来设置缓存(包括注释,所以它可能只是 copypasta)。但是,我不太明白为什么您必须在这里使用反射。

通常,当我想使用在我定义的minSdkVersion 之上的某个 API 级别添加的方法时,我会使用以下模式:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) 
   // do something here

那么为什么这不是HttpResponseCache 的默认模式。使用反射有什么好处?它当然不会增加我的代码的可读性。以这种方式使用反射时,HttpResponseCache 是否真的在 ICS 下工作?

编辑:我这里没有旧的 Android 设备,我的模拟器根本拒绝启动,所以我现在不能简单地测试它。也许它只是在没有反射的情况下可怕地崩溃。

【问题讨论】:

【参考方案1】:

使用反射有什么好处?

首先,引用文档:

这个类是在 Android 4.0 (Ice Cream Sandwich) 中添加的。

“被添加”是指“被添加到Android SDK”,“冰淇淋三明治”是指基于其余部分的 Android 3.2(API 级别 13) JavaDocs。

但是,HttpResponseCache 类本身在框架中存在的时间更长,希望自 Android 1.0 以来给出了他们的建议。但是,该类标有 @hide 注释,因此在 API 级别 13 之前,应用程序无法直接使用它。

使用Build 的Java 版本保护块将避免在旧设备上直接引用此类。但是,它实际上也没有在旧设备上配置缓存。 他们的方法适用于所有版本的 Android,并允许您配置缓存,因为该类从一开始就存在。

Google 明确授权以这种方式使用反射来获取隐藏的类或方法是相当罕见的,这就是您在官方文档中不经常看到它的原因。

【讨论】:

【参考方案2】:

很遗憾,您的建议不适用于旧版本。思考以下问题。他们在新版本中添加了方法install(File, long)。但是调用这个方法的代码被打包到其他jar中。

现在您有了包含HttpResponseCache 的旧版本jar 和调用它的新版本jar。如果你写在那里

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) 
   cache.install(file, number);

NoSuchMethodError 即使 if 的表达式为假,也会被抛出。 使用反射是一种丑陋但有用的技术来防止这种情况。

【讨论】:

以上是关于为啥对 HttpResponseCache 使用反射?的主要内容,如果未能解决你的问题,请参考以下文章

使用 HttpResponseCache 会使应用程序崩溃

HttpResponseCache 在 Android Lollipop 中不起作用

HttpResponseCache 不清除旧文件?

如何在 Android 上使用 HttpsURLConnection 和 HttpResponseCache 强制缓存?

将 LRU 图像缓存与 HTTPResponseCache 结合用于磁盘和内存缓存

java.lang.NoClassDefFoundError 与 HttpResponseCache 和 DiskLruCache