美文网首页
volley 那些细节

volley 那些细节

作者: 寻欢_75dc | 来源:发表于2018-05-04 16:40 被阅读0次

文件上传

http content-type
volley的整体实现流程,我就不写了,哎,看了一个上午主体还是没什么问题,关键在于实现细节,包含的东西才多,所以这里不做过多讨论,言归正传,我们看看volley的一些细节实现吧。

乍一看,我们找遍了整个框架源码,都没发现文件上传写好的API,并且你会惊讶的发现貌似request 实现中只有针对于content-type:application/x-www-form-urlencoded;我去感情这个框架没写好,其实呢?我们先看看下面这段代码.

/** Returns the content type of the POST or PUT body. */
    public String getBodyContentType() {
        return "application/x-www-form-urlencoded; charset=" + getParamsEncoding();
    }
 /**
     * Returns the raw POST or PUT body to be sent.
     *
     * <p>By default, the body consists of the request parameters in
     * application/x-www-form-urlencoded format. When overriding this method, consider overriding
     * {@link #getBodyContentType()} as well to match the new body format.
     *
     * @throws AuthFailureError in the event of auth failure
     */
    public byte[] getBody() throws AuthFailureError {
        Map<String, String> params = getParams();
        if (params != null && params.size() > 0) {
            return encodeParameters(params, getParamsEncoding());
        }
        return null;
    }

    /** Converts <code>params</code> into an application/x-www-form-urlencoded encoded string. */
    private byte[] encodeParameters(Map<String, String> params, String paramsEncoding) {
        StringBuilder encodedParams = new StringBuilder();
        try {
            for (Map.Entry<String, String> entry : params.entrySet()) {
                encodedParams.append(URLEncoder.encode(entry.getKey(), paramsEncoding));
                encodedParams.append('=');
                encodedParams.append(URLEncoder.encode(entry.getValue(), paramsEncoding));
                encodedParams.append('&');
            }
            return encodedParams.toString().getBytes(paramsEncoding);
        } catch (UnsupportedEncodingException uee) {
            throw new RuntimeException("Encoding not supported: " + paramsEncoding, uee);
        }
    }

看到了吧,哎,照这么说其它的实现,我们需要自己实现,文件上传了,于是乎我们依葫芦画瓢,如果要实现文件上传,我们需要改变请求头content-type和body所以具体实现可参照如下,这里只贴关键代码
具体参考Android volley 解析(三)之文件上传篇

 public String getBodyContentType() {
        return "multipart/form-data;charset=utf-8;boundary=" + BOUNDARY;
    }
public byte[] getBody(){
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
StringBuffer sb = new StringBuffer();
sb.append("--" + BOUNDARY);
sb.append("\r\n");
//解释下name 这个你可以默认成key 是服务器解析的key,务必和服务器保持一致.
// filename 服务器保存的这个文件的名称.
sb.append("Content-Disposition:form-data;name=\"file1\";filename=\"test.jpg\"\r\n");
sb.append("content-type:image/jpg\r\n\r\n");

bos.write(sb.toString().getBytes("utf-8"));
bos.write(...图片数据byte[]...);
bos.write("\r\n".getBytes("utf-8"));

bos.write("--" + BOUNDARY + "--" + "\r\n".getBytes("utf-8"));
return bos.toByteArray();
}

以上我们必须实现Request 这个类,并且重写getBody()和getBodyContentType()方法

volley缓存实现.

1 HTTP 缓存

如果大家完全没有缓存这个概念,我推荐大家看这篇
从http开始说Volley缓存
http 缓存原理
表示缓存的请求或者响应头报文

  1. Cache_Control
  2. 在请求头里面If-None-Match / Etag
  3. If-Modified-Since /Last-Modified.
  4. Expires 和 Max-Age,date
  5. 响应状态吗304和200.


    请求头
    响应头
//这是StringRequest 的代码,解析网络结果.
 @Override
    @SuppressWarnings("DefaultCharset")
    protected Response<String> parseNetworkResponse(NetworkResponse response) {
        String parsed;
        try {
            parsed = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
        } catch (UnsupportedEncodingException e) {
            parsed = new String(response.data);
        }
        return Response.success(parsed, HttpHeaderParser.parseCacheHeaders(response));
    }

 public static Cache.Entry parseCacheHeaders(NetworkResponse response) {
        long now = System.currentTimeMillis();

        Map<String, String> headers = response.headers;

        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;

        String serverEtag = null;
        String headerValue;

        //RFC格式.这个表示服务器发送这条消息的时间。
        headerValue = headers.get("Date");
        if (headerValue != null) {
            serverDate = parseDateAsEpoch(headerValue);
        }
        //这个的值有很多种.以下就是private,public,no-cache和no-store,max-age.
        headerValue = headers.get("Cache-Control");
        if (headerValue != null) {
            hasCacheControl = true;
            String[] tokens = headerValue.split(",", 0);
            for (int i = 0; i < tokens.length; i++) {
                String token = tokens[i].trim();
                if (token.equals("no-cache") || token.equals("no-store")) {
                    return null;
                } else if (token.startsWith("max-age=")) {
                    try {
                        maxAge = Long.parseLong(token.substring(8));
                    } catch (Exception e) {
                    }
                    //这个被称为死缓,总缓存时间是 maxAge + staleWhileRevalidate.
                } else if (token.startsWith("stale-while-revalidate=")) {
                    try {
                        staleWhileRevalidate = Long.parseLong(token.substring(23));
                    } catch (Exception e) {

                    }
                    //如果有这个说明must-revalidate.不会使用死缓,过了maxAge期限,则立即请求网络.
                } else if (token.equals("must-revalidate") || token.equals("proxy-revalidate")) {
                    mustRevalidate = true;
                }
            }
        }

        //响应头中缓存的有效时间截止到如Date: Thu, 11 Jul 2015 15:33:24 GMT。是这种RFC格式.
        headerValue = headers.get("Expires");
        if (headerValue != null) {
            //转换成毫秒.
            serverExpires = parseDateAsEpoch(headerValue);
        }

        //这个时间也是RFC格式.
        headerValue = headers.get("Last-Modified");
        if (headerValue != null) {
            lastModified = parseDateAsEpoch(headerValue);
        }

        serverEtag = headers.get("ETag");

        // Cache-Control takes precedence over an Expires header, even if both exist and Expires
        // is more restrictive.
        if (hasCacheControl) {
            softExpire = now + maxAge * 1000;
            finalExpire = mustRevalidate ? softExpire : softExpire + staleWhileRevalidate * 1000;

            //expires(1.0) 和Cache-Control(1.1)那些过去
        } else if (serverDate > 0 && serverExpires >= serverDate) {
            // 缓存消息
            softExpire = now + (serverExpires - serverDate);
            finalExpire = softExpire;
        }

        Cache.Entry entry = new Cache.Entry();
        entry.data = response.data;
        entry.etag = serverEtag;
        entry.softTtl = softExpire;
        entry.ttl = finalExpire;
        entry.serverDate = serverDate;
        entry.lastModified = lastModified;
        entry.responseHeaders = headers;
        entry.allResponseHeaders = response.allHeaders;

        return entry;
    }

2 DiskBasedCache 内存和磁盘缓存

LinkedHashMap

public class DiskBasedCache implements Cache {
/** 磁盘缓存,默认5M. */
    private static final int DEFAULT_DISK_USAGE_BYTES = 5 * 1024 * 1024;

     //这个位置是内存缓存.LinkedHash 符合LRU 的规则.
    private final Map<String, CacheHeader> mEntries = new LinkedHashMap<>(16, .75f, true);

put(){};
get(){};
//这个函数是说 如果剩余空间(超过了期望的最大缓存)不足,就会删除文件.删除文件规则,显示跟LRU算法有关.
pruneIfNeeded(int needSpace);

}

总结

有些东西写的不够完善后期有时间都会慢慢补上,请广大高手们手下留情啊,欢迎提出问题,一起讨论.

为什么volley 适合数据量小的频繁请求?
volley中为了提高请求处理的速度,采用了ByteArrayPool进行内存中的数据存储的,如果下载大量的数据,这个存储空间就会溢出,所以不适合大量的数据,但是由于他的这个存储空间是内存中分配的,当存储的时候优是从ByteArrayPool中取出一块已经分配的内存区域, 不必每次存数据都要进行内存分配,而是先查找缓冲池中有无适合的内存区域,如果有,直接拿来用,从而减少内存分配的次数 ,所以他比较适合大量的数据量少的网络数据交互情况。

相关文章

  • volley 那些细节

    文件上传 http content-typevolley的整体实现流程,我就不写了,哎,看了一个上午主体还是没什么...

  • Volley具体流程图(配代码)

    只简要分析Volley大体原理,无细节,无Volley使用教程。 使用Volley时必要的两步: 第一步通过Vol...

  • Volley 总纲

    前言 之前写过很多篇关于volley源码的分析文章,这些文章都是深入到volley源码的细节去分析和扩展。最近重新...

  • 再读Volley-缓存策略

    再读Volley 第一次看Volley的代码的时候只是大概地理清了它的结构而没有做细节上的记录,但是看了这两篇文章...

  • Android:Volley的使用和Volley源码分析

    Volley网络框架 Volley的简单使用 Volley源码分析 }

  • Volley

    Volley地址Volley, Volley是Google开源的一个网络框架 Demo 通过Volley.newR...

  • 1、volley 官方教程-简介、配置

    文章摘要1、Volley 简介2、Volley库配置 英文文献 Github Volley下载地址 Volley是...

  • Volley学习笔记

    Volley的增强工具 Volley Request Manager adb logcat中显示Volley lo...

  • Volley学习

    Volley学习 参考文章 Android Volley完全解析(一),初识Volley的基本用法Android ...

  • Android异步网络请求框架-Volley

    Android 异步网络请求框架-Volley 1. 功能介绍 1.1. Volley Volley 是 Goog...

网友评论

      本文标题:volley 那些细节

      本文链接:https://www.haomeiwen.com/subject/zvcdrftx.html