当前位置: 首页 > news >正文

android网络开源框架volley(五岁以下儿童)——volley一些细节

    最近的一次volley整理出下一个。我以前没有再次遭遇了一些小问题,在该记录:


1、HttpUrlConnection DELETE 信息不能加入body问题:java.net.ProtocolException: DELETE does not support writing


    这个能够算是一个系统级的bug,为什么这么说,请看这里,这个问题在java8中才得以解决。没办法直接过去,咱就绕过去。查看HttpUrlConnection,我们发现他是一个抽象类,因此能够试试能不能通过它的其它实现来达到我们的目的。

终于我们决定使用okhttp这个实现。地址为:https://github.com/square/okhttp。

接着我们还得去看看volley的源代码,因为我们的app兼容的最低版本号是4.0。因此我们知道终于调用的是HurlStack:

    public static RequestQueue newRequestQueue(Context context, HttpStack stack) {
...
        if (stack == null) {
            if (Build.VERSION.SDK_INT >= 9) {
                stack = new HurlStack();
            } else {
                // Prior to Gingerbread, HttpUrlConnection was unreliable.
                // See: http://android-developers.blogspot.com/2011/09/androids-http-clients.html
                stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent));
            }
        }
...
    }

因此我们仅仅须要将HurlStack的相关代码改动就可以,例如以下:

volley.java

public static RequestQueue newRequestQueue(Context context, HttpStack stack) {
...
        if (stack == null) {
            if (Build.VERSION.SDK_INT >= 9) {
                // old way: stack = new HurlStack();
            		// http://square.github.io/okhttp/
                stack = new HurlStack(null, null, new OkUrlFactory(new OkHttpClient()));
            } else {
                // Prior to Gingerbread, HttpUrlConnection was unreliable.
                // See: http://android-developers.blogspot.com/2011/09/androids-http-clients.html
                stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent));
            }
        }
...
    }
HurlStack.java

/**
 * An {@link HttpStack} based on {@link HttpURLConnection}.
 */
public class HurlStack implements HttpStack {

    private final OkUrlFactory mOkUrlFactory; 

    /**
     * @param urlRewriter Rewriter to use for request URLs
     * @param sslSocketFactory SSL factory to use for HTTPS connections
     * @param okUrlFactory solution delete body(https://github.com/square/okhttp)
     */
    public HurlStack(UrlRewriter urlRewriter, SSLSocketFactory sslSocketFactory, OkUrlFactory okUrlFactory) {
        mUrlRewriter = urlRewriter;
        mSslSocketFactory = sslSocketFactory;
        mOkUrlFactory = okUrlFactory;
    }
    /**
     * Create an {@link HttpURLConnection} for the specified {@code url}.
     */
    protected HttpURLConnection createConnection(URL url) throws IOException {
		if(null != mOkUrlFactory){
			return mOkUrlFactory.open(url);
		}
        return (HttpURLConnection) url.openConnection();
    }


    @SuppressWarnings("deprecation")
    /* package */ 
    static void setConnectionParametersForRequest(HttpURLConnection connection,
            Request<?

> request) throws IOException, AuthFailureError { switch (request.getMethod()) { ... case Method.DELETE: connection.setRequestMethod("DELETE"); addBodyIfExists(connection, request); break; ... default: throw new IllegalStateException("Unknown method type."); } } ... }


2015-04-26更新:

再次使用到须要使用到okhttp,回头看下上面的代码,不知道当时怎么想的。使用这么复杂的方法引入Okhttp。预计是脑袋进水了。

再来看下这种方法:newRequestQueue(Context context, HttpStack stack),有两个參数:context和HttpStack,这里是要传入自己的HttpStack就好了。

那么我们用OKhttp的实现:

/**
 * An {@link com.android.volley.toolbox.HttpStack HttpStack} implementation which
 * uses OkHttp as its transport.
 */
public class OkHttpStack extends HurlStack {
  private final OkHttpClient client;
 
  public OkHttpStack() {
    this(new OkHttpClient());
  }
 
  public OkHttpStack(OkHttpClient client) {
    if (client == null) {
      throw new NullPointerException("Client must not be null.");
    }
    this.client = client;
  }
 
  @Override protected HttpURLConnection createConnection(URL url) throws IOException {
    return client.open(url);
  }   
}
參考: https://gist.github.com/JakeWharton/5616899

2、关于(改动)volley的缓存


    volley有完整的一套缓存机制。而眼下我们想做个简单的需求:部分界面(差点儿不会改动的)简单的做一定时间的缓存,研究了下代码发现非常easy改动达到自己的目的(有时间在分析下volley的缓存机制,这个一定要做)。简单来说改动一个地方:request.parseNetworkResponse中的

HttpHeaderParser(此处突然感慨volley的设计TMD灵活了。想怎么改就怎么改)。HttpHeaderParser改动后的代码例如以下:

/**
 * 改动后的。用户处理缓存
 */
public class BHHttpHeaderParser {

    /**
     * Extracts a {@link Cache.Entry} from a {@link NetworkResponse}.
     *
     * @param response The network response to parse headers from
     * @return a cache entry for the given response, or null if the response is not cacheable.
     */
    public static Cache.Entry parseCacheHeaders(NetworkResponse response, boolean isCustomCache) {
...
        if(isCustomCache){
        		softExpire = now + Config.HTTP_CACHE_TTL;
        } else {
	        	if (hasCacheControl) {
	            softExpire = now + maxAge * 1000;
	        } else if (serverDate > 0 && serverExpires >= serverDate) {
	            // Default semantic for Expire header in HTTP specification is softExpire.
	            softExpire = now + (serverExpires - serverDate);
	        }
        }
        
        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;

        return entry;
    }
...
}

此处大家能够发现,我们主要是依据自己定义的变量决定怎样改动cache的TTL来达到自己的目的。


3、HttpUrlConnection与PATCH(2015-04-26)


在使用Volley发送PATCH请求的时候,我们可能会遇到这种问题:Unknown method 'PATCH'; must be one of [OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE]。这个时候你的第一反应是什么呢?是Volley不支持PATCH请求吗?换成OkHttp是不是能够呢?查看了下Volley的源代码,在HurlHttp.java中发现例如以下一段:

/* package */ 
static void setConnectionParametersForRequest(HttpURLConnection connection,
            Request<?> request) throws IOException, AuthFailureError {
        switch (request.getMethod()) {
            case Method.DEPRECATED_GET_OR_POST:
                // This is the deprecated way that needs to be handled for backwards compatibility.
                // If the request's post body is null, then the assumption is that the request is
                // GET.  Otherwise, it is assumed that the request is a POST.
                byte[] postBody = request.getPostBody();
                if (postBody != null) {
                    // Prepare output. There is no need to set Content-Length explicitly,
                    // since this is handled by HttpURLConnection using the size of the prepared
                    // output stream.
                    connection.setDoOutput(true);
                    connection.setRequestMethod("POST");
                    connection.addRequestProperty(HEADER_CONTENT_TYPE,
                            request.getPostBodyContentType());
                    DataOutputStream out = new DataOutputStream(connection.getOutputStream());
                    out.write(postBody);
                    out.close();
                }
                break;
            case Method.GET:
                // Not necessary to set the request method because connection defaults to GET but
                // being explicit here.
                connection.setRequestMethod("GET");
                break;
            case Method.DELETE:
                connection.setRequestMethod("DELETE");
                break;
            case Method.POST:
                connection.setRequestMethod("POST");
                addBodyIfExists(connection, request);
                break;
            case Method.PUT:
                connection.setRequestMethod("PUT");
                addBodyIfExists(connection, request);
                break;
            case Method.HEAD:
                connection.setRequestMethod("HEAD");
                break;
            case Method.OPTIONS:
                connection.setRequestMethod("OPTIONS");
                break;
            case Method.TRACE:
                connection.setRequestMethod("TRACE");
                break;
            case Method.PATCH:
                connection.setRequestMethod("PATCH");
                addBodyIfExists(connection, request);
                break;
            default:
                throw new IllegalStateException("Unknown method type.");
        }
    }
通过这段代码。我们知道,Volley对PATCH还是支持的。在细看下错误这个是有HttpUrlConnection抛出的。因此我们须要在这方面下手。

这里有一个參考:

https://github.com/adriancole/retrofit/commit/e704b800878b2e37f5ac98b0139cb4994618ace0



以后有其它关于volley它被记录在这个摘要。


版权声明:本文博主原创文章,博客,未经同意不得转载。

相关文章:

  • 查看自己的电脑的内存扩充-最大
  • MySQL错误Another MySQL daemon already running with the same unix socket.v
  • CSS制作响应式正方形及其应用
  • css中attribute selector及pseudo class
  • “考虑不全面”导致的大问题!!!
  • [Linux]于Mac在配置Linuxserver安装Nginx+PHP
  • Multimodal —— 看图说话(Image Caption)任务的论文笔记(二)引入attention机制
  • NFS服务配置固定端口
  • 别再用 MongoDB 了!
  • 第十章:异常处理
  • export Jar from eclipse (总结)
  • grep命令
  • MVC TIP8:为控制器增加有参构造函数(为了注入等其它用途)
  • 自己做的一种计算器算法的设计..不知道代码是否有bug
  • bat无故报错打印混乱的解决
  • 【技术性】Search知识
  • C++类的相互关联
  • Linux快速复制或删除大量小文件
  • Linux快速配置 VIM 实现语法高亮 补全 缩进等功能
  • Markdown 语法简单说明
  • Python 使用 Tornado 框架实现 WebHook 自动部署 Git 项目
  • TiDB 源码阅读系列文章(十)Chunk 和执行框架简介
  • uva 10370 Above Average
  • 不上全站https的网站你们就等着被恶心死吧
  • 聊聊sentinel的DegradeSlot
  • 前端自动化解决方案
  • 深度解析利用ES6进行Promise封装总结
  • 阿里云ACE认证学习知识点梳理
  • 分布式关系型数据库服务 DRDS 支持显示的 Prepare 及逻辑库锁功能等多项能力 ...
  • 你学不懂C语言,是因为不懂编写C程序的7个步骤 ...
  • ​Distil-Whisper:比Whisper快6倍,体积小50%的语音识别模型
  • ​linux启动进程的方式
  • ​软考-高级-系统架构设计师教程(清华第2版)【第1章-绪论-思维导图】​
  • # 手柄编程_北通阿修罗3动手评:一款兼具功能、操控性的电竞手柄
  • #define、const、typedef的差别
  • #多叉树深度遍历_结合深度学习的视频编码方法--帧内预测
  • #基础#使用Jupyter进行Notebook的转换 .ipynb文件导出为.md文件
  • (1)(1.9) MSP (version 4.2)
  • (51单片机)第五章-A/D和D/A工作原理-A/D
  • (9)目标检测_SSD的原理
  • (Redis使用系列) SpirngBoot中关于Redis的值的各种方式的存储与取出 三
  • (编译到47%失败)to be deleted
  • (二)【Jmeter】专栏实战项目靶场drupal部署
  • (附源码)spring boot基于Java的电影院售票与管理系统毕业设计 011449
  • (经验分享)作为一名普通本科计算机专业学生,我大学四年到底走了多少弯路
  • (入门自用)--C++--抽象类--多态原理--虚表--1020
  • (十六)串口UART
  • (原創) 如何刪除Windows Live Writer留在本機的文章? (Web) (Windows Live Writer)
  • (转) RFS+AutoItLibrary测试web对话框
  • (转)3D模板阴影原理
  • (转)甲方乙方——赵民谈找工作
  • .Net FrameWork总结
  • .Net 中的反射(动态创建类型实例) - Part.4(转自http://www.tracefact.net/CLR-and-Framework/Reflection-Part4.aspx)...
  • .NET/C# 的字符串暂存池
  • .NET/C# 使窗口永不激活(No Activate 永不获得焦点)