网络通信框架Volley
1,volley的介绍以及特点
1,概念
volley 是 Goole I/O 2013上发布的网络通信库,使网络通信更快、更简单、更健壮。
2,Volley名称的由来
a burst or emission of many things or a large amount at once
翻译:许多东西或大量的爆裂或散发
3,优点
物理质量:
使用Volley 需要Volley.jar(120k),加上自己的封装最多140k。
使用OkHttp需要 okio.jar (80k), okhttp.jar(330k)这2个jar包,总大小差不多400k,加上自己的封装,差不多得410k。
性能优势:
非常适合进行数据量不大,但通信频繁的网络操作
可直接在主线程调用服务端并处理返回结果
可以取消请求,容易扩展,面向接口编程
网络请求线程NetworkDispatcher默认开启了4个,线程优化
通过使用标准的HTTP缓存机制保持磁盘和内存响应的一致(DiskBasedCache)
4,缺点
底层使用的是httpclient、HttpURLConnection
6.0不支持httpclient了,如果想支持得添加org.apache.http.legacy.jar
对大文件下载 Volley的表现非常糟糕
只支持http请求
图片加载性能一般
5,Volley 的使用场景和使用方式
场景:
用于请求比较频繁,但是数据量又不大,如列表刷新,加载等!
使用方式:
Volley的基本用法
Volley加载网络图片
定制自己的Request
2,volley的功能摘要
Json,图像等异步下载
缓存
可以取消请求
和Activity的生命周期联动
3,使用前的配置
AndroidManifest.xml中添加权限:
<uses-permission android:name="android.permission.INTERNET" />
modle目录下build.gradle配置:
dependencies {
compile 'eu.the4thfloor.volley:com.android.volley:2015.05.28'
}
5,使用步骤
1,创建请求队列(不要重复创建队列,只要一个),
通过Volley的静态方法RequestQueue newRequestQueue(Context context)
2,创建请求
通过构造方法Request(int method, String url, Response.ErrorListener listener)
3,将请求加入队列.
通过RequestQueue的方法RequestQueue add(Request<T> request)
6,具体的使用
StringRequest
请求结果返回字符串.
get请求
post请求
添加请求参数,重写Map<String, String> getParams(),创建一个map,并且将参数放到map中返回.
添加请求头参数,重写Map<String, String> getHeaders(),创建一个map,并且将请求头参数放到map中返回.
ImageRequest
请求结果返回Bitmap
断网状态下会读取缓存
JsonRequest
JsonObjectRequest
请求结果返回JsonObject
JsonArrayRequest
请求结果返回JsonArray
ImageLoader
加载网络图片到ImageView,可以设置加载中,加载失败后的默认本地图片.
缓存的处理暴露接口对外实现处理。
至于大家想用内存缓存,还是磁盘缓存,看各自应用场景了
NetworkImageView+ImageLoader
自定义控件,继承自ImageView,可以加载网络图片
断网状态下会读取缓存
GsonRequest
自定义请求,请求结果返回解析后的java对象
Request的其他操作
请求设置是否启用缓存
参数:true则缓存,false则不进行缓存,若不设置默认是缓存的.
Request<?> setShouldCache(boolean shouldCache)
请求设置标记
Request<?> setTag(Object tag)
请求取消
Volley可以保证响应处理函数(就是onResponse()和onErroeResponse())不会被调用。
Request的方法: cancel()
取消发送请求
//通常可以在onStop()或者onDetroy()中调用cancelAll()。
用RequestQueue的方法: cancelAll(final Object tag)
Cache硬盘缓存数据
1,缓存优势
我们知道,当客户端在请求网络数据的时候,是需要消耗流量的,特别是对于移动端用户来说,对于流量的控制要求很高。所以在做网络请求的时候,如果对数据更新要求不是特别高,往往都会用到缓存机 制,一方面能减少对服务端的请求,控制流量;另一方面,当客户端在没有网络的情况下也能看到上一次请求的数据,这样使用户体验更佳,如下图,微信朋友圈在没有网络的情况下,依然能看到朋友们的动 态
2,特点
Volley框架内部自己处理了DiskBasedCache硬盘缓存,但是没有处理LruCache内存缓存,因为一般在处理图片的问题上才更多的用到 LruCache缓存,但是它提供了一个ImageCache接口供我们自己实现,该接口默认需要实现两个方法:
getBitmap(String key)
和putBitmap(String key, Bitmap bitmap),
由此可见,这就是从缓存中拿数据和存入数据的两个方法,我们完全可以使用LruCache来实现内存缓存
3,缓存的使用
(缓存在Cache目录下)
Cache是用RequestQueue的方法:Cache getCache()来获取的.
读取缓存数据:
用Cache的方法: Entry get(String key);
得到entry.data就是缓存的数据,是一个byte[]数组.
最后在将这个byte[]数组转换成我们想要的数据类型.
删除指定缓存数据:
参数:key对应的键,例如图片的url地址.
remove(String key)
清空缓存的数据:
方式1:用Cache的方法,clear()
方式2:ClearCacheRequest
ClearCacheRequest ccr = new ClearCacheRequest(reqQueue.getCache(),
new Runnable() {
@Override
public void run() {
//主线程序执行代码.
}
});
ccr.setTag(this);
reqQueue.add(ccr);
失效缓存的数据:
使缓存的数据失效过期,但是不会清空数据,缓存已经过期,则重新请求网络
用Cache的方法,initialize()
添加缓存数据:
// mCache.put(request.getCacheKey(), response.cacheEntry);
用Cache的方法,put(String key, Entry entry)
已经封装的操作.
Cache.Entry entry = new Cache.Entry();
entry.data = response.data;
entry.etag = serverEtag;
entry.softTtl = softExpire;
entry.ttl = entry.softTtl;
entry.serverDate = serverDate;
entry.responseHeaders = headers;
断网读取缓存分析:
断网图片可以加载:
因为Volley内部本身就处理了数据的硬盘缓存,通过Volley请求的数据默认情况下都会缓存到cache/volley缓存目录下,所以,正因为它内部具有硬盘缓存,使得 Volley在请求网络数据时候首先会查找volley缓存目录下是否有该缓存文件,如果有则从缓存中取出,没有则通过网络请求获取数据。那么Volley是怎么判断该缓存文 件的数据是否是我们请求需要的数据呢?答案是通过url来做判断,我们刚刚不是打开了缓存文件么,不管是json类型的还是图片的缓存文件,开头部分都是该数据的url,所以就是通过url做 判断。
断网json字符串数据加载不出来
我们刚刚说了Volley请求网络数据时候都会先从缓存中找,当然json字符串数据也一样,不过,这里我要引入一个概念,就是Volley从缓存文件中拿取数据的时候,都会先判断这个缓存 文件的ttl(“过期时间”)是否过期,这个ttl的值是由缓存中的Age或max-age的值来计算的,而Age值又是从Response中的
cache-control得到的,我们可以在上面的图片缓存文件的第四行可以看到图片的缓存文件有maxage而且有值,而json数据的缓存文件则没有,
所以它的age为0,从而一直都处于过期状态,所以Volley就不会从这个json缓存文件中取数据而是需要通过网络请求获取数据。
对于json数据过期,其实取决于服务器传回来的Header信息中CacheControl的信息。
如何来获取字符串类型的数据?
1,通过控制服务器传回来的Header信息中CacheControl的信息来控制,修改其Age或max-age的值
服务器端必须设置头部,告诉Volley这条数据是可以缓存的
response.setHeader("cache-control", "public, max-age=43200");
2,通过cache对象根据url去读取本地的磁盘缓存.
Entry
/** 服务端返回数据的主要内容 */
public byte[] data;
/** 这个是与与http请求缓存相关的标签 */
public String etag;
/** 服务器的返回来数据的时间 */
public long serverDate;
/** The last modified date for the requested object. */
public long lastModified;
/** TTL 缓存过期时间. */
public long ttl;
/** Soft TTL 缓存新鲜度时间. */
public long softTtl;
/** 服务器还回来的头部信息 */
public Map<String, String> responseHeaders = Collections.emptyMap();
/** 是否过期 */
public boolean isExpired() {
return this.ttl < System.currentTimeMillis();
}
/** 是否需要刷新 */
public boolean refreshNeeded() {
return this.softTtl < System.currentTimeMillis();
}
CacheHeader
static class CacheHeader {
/** 缓存文件的大小 */
public long size;
/** 缓存文件的唯一标识 */
public String key;
/** 这个是与与http请求缓存相关的标签 */
public String etag;
/** 服务器的返回来数据的时间 */
public long serverDate;
/** TTL 缓存过期时间. */
public long ttl;
/** Soft TTL 缓存新鲜度时间. */
public long softTtl;
/** 服务器还回来的头部信息. */
public Map<String, String> responseHeaders;
}
DiskBasedCache
把缓存数据Entry写进磁盘里
put(String key, Entry entry)
从缓存数据里取缓存
Entry get(String key)
将url生成文件名字
getFilenameForKey(String key)
HttpHeaderParser
Cache.Entry parseCacheHeaders(NetworkResponse response)
long serverDate = 0;
long lastModified = 0;
long serverExpires = 0;
long softExpire = 0;
long finalExpire = 0;
long maxAge = 0;
long staleWhileRevalidate = 0;
boolean hasCacheControl = false;
boolean mustRevalidate = false;
图片缓存分析
image.png
volley功能结构
image.png
数据缓存分析
image.png
网友评论