android http请求缓存,Android打造属于自己的缓存网络请求【原创】

本文介绍了作者在开发自己的网络请求框架过程中,如何解决缓存控制、Cookie管理、请求取消、并发、重复请求、优先级和重试机制等问题。通过设置缓存策略,实现了两级缓存(内存和磁盘),并讨论了Cookie的获取方法。此外,还提出了使用队列管理请求,以实现请求取消、避免重复请求和调整请求优先级的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

现在的网络应用越来越平常化,几乎每个应用都比不可少的要与网络接轨。我们在开发的时候,网络请求写的也算是家常便饭了。现在市面上的网络请求框架很多,举几个例子比如:Volley, AsyncHttpClient,

xUtils,okHttp,等等,很多。但是在写了这么多的应用之后发现,一直研究别人的代码如何去用,还不如自己写一个。什么都在自己掌控之内,腰不酸腿也不疼了。经过种种思量之后,打算写自己的网络请求框架。既然决定要写,那就要把之前遇到的问题全部解决,这些问题包括:

1.缓存控制,多样性控制,什么意思呢?比如请求失败后是否使用缓存,请求超时了是否使用缓存等。

2.Cookie的问题。

3.请求的取消

4.请求的并发

5.重复请求的问题

6.请求的优先级

7.请求失败重试机制

有了目标,那么我们就针对这些问题一个一个来解决。

第一条:

缓存的控制,缓存我设计了两级缓存,即内存缓存LruCache,与磁盘缓存DiskLruCache,在写的过程中发现缓存需要解决的问题是对象的存储问题,我使用了一个CacheData的缓存对象,内部封装了数据源,缓存过期等相关控制,这一个对象就相当于一个请求的缓存数据,那么我们需要对这个对象进行存储,内存存储还好,因为LruCache本身就是可缓存对象的,而磁盘缓存DiskLruCache 存储起来就需要做些处理了,把一个对象存储到磁盘,经过搜索相关资料,只能使用序列化的方式,让CacheData对象实现序列化接口,存储的时候我们就可以使用“ObjectOutputStream”来存储对象。

下面是我写好的一个存储对象函数:

/**

* set the data to disk cache

* @param originalKey

*/

public void setDataToDiskCache(String originalKey,ValueType value){

try {

String key = hashKeyForDisk(originalKey);

DiskLruCache.Editor editor = mDiskLruCache.edit(key);

if (editor != null) {

OutputStream outputStream = editor.newOutputStream(0);

ObjectOutputStream oos=new ObjectOutputStream(outputStream);

if (value!=null) {

oos.writeObject(value);

}

/*if (oos!=null) {

oos.close();

}*/

if (getDataFromDiskCache(originalKey)==null) {

editor.commit();

} else {

editor.abort();

}

}

mDiskLruCache.flush();

} catch (IOException e) {

e.printStackTrace();

}

}

上面的ValueType是一个泛型类。

这样缓存存储问题先搞定了。接下来是设计缓存的控制,这个部分比较绕。我的设计如下:

cacheConfig.setShouldCache(true);  // 是否允许缓存 ①为true 时,请求完成后更新缓存,②为false 时,直接使用请求数据,请求完成后不更新缓存

cacheConfig.setUseCacheDataAnyway(false); //是否总是使用缓存数据 ①为true 时 直接使用缓存数据,不管缓存有没有过期,并在请求完成后更新缓存。如果缓存不存在,则进行网络请求,请求完成后使用最新数据并更新缓存

cacheConfig.setUseCacheDataWhenRequestFailed(true);  //当网络请求失败的时候是否使用缓存数据①为 true 时 在请求失败的时候使用缓存,②为 false 时,请求失败时不使用缓存

cacheConfig.setUseCacheDataWhenTimeout(true); //当网络请求超时后直接使用缓存数据,后面在网络请求完成后更新缓存

cacheConfig.setUseCacheDataWhenUnexpired(true);  //当缓存存在并未过期的时候是否使用缓存数据①为 true 时 当缓存数据存在并且未过期,使用缓存数据,如果缓存不存在或者过期,则进行网络请求,请求完成后使用最新数据,且如果允许缓存,更新缓存②为false 时 直接进行网络请求,请求完成后使用最新数据,且如果允许缓存,更新缓存

缓存控制问题也搞定了。

第二条:

Cookie的问题,其实这个问题也不算个问题,为什么这么说呢?现在Android中的网络请求有两种方式,一种是Android为我们提供的HttpUrlConnection,另一种就是Apache的HttpClient,无论哪种请求方式,我们获得Cookie,只需要从这两个对象中便可直接拿到,既然这么简单,又为什么单独拿出来说一下,因为之前使用过一次别人的框架,项目中需要获取SessionId,悲催的发现这个框架没有获得Cookie的方法,也没有获取HttpUrlConnection或者HttpClient对象的接口,问了作者,他说暂时没办法,怎么搞勒,只能自己改源码咯,又要花一番功夫去研究下他的代码,好歹最后搞定了这个问题。

第三条:请求的取消

这个问题,说简单不简单,说难其实也不难,后面会说到这个问题

第四条:

请求的并发,这个算比较重要的问题,很容易忽略,在之前的项目中,使用了一个网络请求对象,同时进行两请求,结果发现其中一个请求始终无法获取返回值,找了很久终于发现了这个问题,作者请求框架中使用了一个线程进行网络请求,所以没办法并发。ok,知道了问题,我们的解决方法也出来了,”多线程“并发即可

第五条:

重复请求的问题,模拟一个场景:在一个电商的项目中,用户进入一个商品详情页面,退出进汝,再退出再进入,反复多次。这样同一个请求就请求了多次,每次都会连接网络。那你会说,不是有缓存了吗,后面再请求不就会使用缓存了吗!?当前面的请求完成后确实会达到这个效果,但是在实际中,可能网速慢等多种情况,前面的请求还没完成呢,这时候又发起了第二个第三个请求,这样就连接了三次网络,造成流量的浪费,电量等资源的损耗。所以这个问题需要我们进行严格的控制,怎么控制,看后面

第六条:

请求的优先级,关于优先级,与上面一样,后面一起说

第七条:

重试机制,这个我们可以定义一个策略,并且这个这个策略可以自定义

这七个问题,其中”第三条“”第五条“”第六条“,请求的取消,请求重复问题,请求的优先级问题,在Volley中已经有了很好的实现,而我们可以参考volley的做法,原理是使用队列

把请求加入队列中,当我们需要取消请求的时候,只需要把它从队列中移除即可

而请求重复的问题,也可以得到解决,当发现队列中有相同的请求时,把后面的请求通通加入一个第三方队列,当请求完成时,释放第三方队列,释放后的请求就可以使用前面的请求的缓存数据了

同样的,优先级问题也可以通过队列解决,在队列queue中,有很多不同的队列类,其中PriorityBlockingQueue就是一个可以进行自定义排序的队列,我们可以从这方面着手

这样所有的问题就得到了解决。下面就是编码了,代码已经完成了,90%,目前未实现的功能有重试机制,这个后面会陆续加上,下面放一张,画的简单的流程草图

XDroid%E8%AF%B7%E6%B1%82%E7%AE%80%E5%8D%95%E6%B5%81%E7%A8%8B%E5%9B%BE.png

转载时请注明出处及相应链接,本文永久地址:https://blog.yayuanzi.com/11378.html

75d087ef9a9fb11dc373caaf33adbf7f.png

微信打赏

支付宝打赏

感谢您对作者wangbin的打赏,我们会更加努力!    如果您想成为作者,请点我

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值