volley 怎么使用,网上一堆教程。前段时间我们使用volley出问题了,可能是对volley不熟悉,自己就稍微研究了一下。记录下来,希望对大家有用。
第一点:创建RequestQueue 队列,一个项目中创建一个就可以了,详情请看Google 发布的 volley的视频,https://www.youtube.com/watch?v=yhv8l9F44qo&feature=player_embedded,大概在15分钟左右有专门的说明。之前一直看郭霖郭神的blog,他上面说 基本上在每一个需要和网络交互的Activity中创建一个RequestQueue对象就足够了,我的建议还是以官方为主, 有篇blog写的挺好
http://www.daxueit.com/article/4889-3.html 说 RequestQueue 就相当于航空母舰,一个项目中又一个这个就可以了,之前做过实验,开了10个线程,一直创建RequestQueue 队列,然后请求网络,
代码入下:
private void multiThreadAndMultiQueue() {
for (int i = 0; i < 10; i++) {
new Thread() {
@Override
public void run() {
super.run();
while (true) {
request优快云();
SystemClock.sleep(1000);
}
}
}.start();
}
}
private void request优快云() {
RequestQueue mQueue = Volley.newRequestQueue(MainActivity.this);
StringRequest stringRequest = new StringRequest("http://www.youkuaiyun.com/,
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
Log.d(TAG, Thread.currentThread().getId() + " ----->" + response);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.e("hoyouly", error.getMessage(), error);
}
});
mQueue.add(stringRequest);
}
很快就出现了OOM异常,异常如下,
java.lang.OutOfMemoryError:
at com.android.volley.toolbox.DiskBasedCache.streamToBytes(Unknown Source)
at com.android.volley.toolbox.DiskBasedCache.readString(Unknown Source)
at com.android.volley.toolbox.DiskBasedCache.readStringStringMap(Unknown Source)
at com.android.volley.toolbox.DiskBasedCache$CacheHeader.readHeader(Unknown Source)
at com.android.volley.toolbox.DiskBasedCache.initialize(Unknown Source)
at com.android.volley.CacheDispatcher.run(Unknown Source)
而如果把 RequestQueue mQueue = Volley.newRequestQueue(MainActivity.this);变成成员变量,只初始化一次,就一切都正常了,
所以按照官方的,设置一个单利,一个项目中只创建一个RequestQueue对象,多了一是浪费资源,二是可能出现很多问题
而且如果查看volley的源码可以知道,创建一个RequestQueue对象,里面会开启四个请求网络的线程,一个缓存线程,并且这五个线程是一直都开启循环着的,里面是run方法可以说是一个死循环的,while(true){},我相信这五个线程应该就已经够我们使用了,并且请求网络的线程还可以扩大,没有必要设置多余的队列来干扰我们的项目。
第二点是关于volley 写入缓存的步骤:
首先需要根据得到的数据,判断是否需要缓存,并且缓存有数据
if (request.shouldCache() && response.cacheEntry != null) {
mCache.put(request.getCacheKey(), response.cacheEntry);//根据URL,把需要缓存的数据写入到缓存,
request.addMarker("network-cache-written");
}
可以写入数据:
会根据传入的 request.getCacheKey() 其实就是方位的网络URL,根据一定的规则生成一个文件名
规则就是 把这个url 一分为两份,url.length/2 截取前半部分字符串得到该 hashcode + 后半部分的hashcode 两段hashcode 字符串相加,就是改文件名
文件的路径目录 /data/data/<包名>/cache/volley/+
写文件部分:
(1)写入的是一个默认的数字:一个魔法数字:CACHE_MAGIC = 0x20150306 100000000101010000001100000110,
调用的是writeInt( ),规则就是把数字 先右移N*8(0,1,2,3)& oxff 然后写到OutputStream中
(2)把url 写入,调用的是 writeString()
1:规则就是把该url根据UTF-8 转换成byte[] 数组,
2:调用 writeLong()方法,把byte数组的按照一定的规则长度写入,规则就是,右移N*8(0,1,2,3,4,5,6,7) 然后写到
3:调用 os.write(b, 0, b.length);把url的长度写入
(3) 还需要写入的是:
writeString(os, etag == null ? "" : etag);
writeLong(os, serverDate);
writeLong(os, lastModified);
writeLong(os, ttl);
writeLong(os, softTtl);
(4)把获取的相应头写入进去 调用 writeStringStringMap(responseHeaders, os);
规则:
1:responseHeaders 是一个map对象,不为null的时候,为null,则调用 writeInt(os, 0);
把responseHeaders的长度,调用 writeInt()写进入
2: 循环变量这个集合,先得到key 调用writeString()写入,然后得到value,同样调用writeString() 写入
(5)写完后刷新数据 os.flush();
(6)前面这么多步骤,只是写相应头文件,接下来就是写入真正的数据: fos.write(entry.data);
(7) 关闭流 fos.close();