为啥对 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 在 Android Lollipop 中不起作用
如何在 Android 上使用 HttpsURLConnection 和 HttpResponseCache 强制缓存?
将 LRU 图像缓存与 HTTPResponseCache 结合用于磁盘和内存缓存
java.lang.NoClassDefFoundError 与 HttpResponseCache 和 DiskLruCache