关于volley的一点自己的理解

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) {
                        requestCSDN();
                        SystemClock.sleep(1000);
                    }
                }
            }.start();
        }
    }


     private void requestCSDN() {
        RequestQueue mQueue = Volley.newRequestQueue(MainActivity.this);
        StringRequest stringRequest = new StringRequest("http://www.csdn.net/,
                new Response.Listener() {
                    @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();



你可能感兴趣的:(Android,技术小结,volley)