文档章节

Android-网络通信框架Volley使用详解

新年
 新年
发布于 2015/06/11 11:20
字数 2890
阅读 1497
收藏 13

1 Volley发送get请求:


public void getJson() {

    String url = "http://"+host+":8080/web/json.jsp?username=xjs&password=123456";

    mQueue.add(new JsonObjectRequest(Method.GET, url, null,

        new Listener<jsonobject>() {

            @Override

            public void onResponse(JSONObject response) {

                Log.e(TAG, "response : " + response.toString());

            }

        }, new Response.ErrorListener() {

            @Override

            public void onErrorResponse(VolleyError error) {

                String err = error.getMessage();

                Log.e(TAG, "err : " + err);

            }

        }));

}



///////////////////////////////////////////////////////////////////////////////////////////

2 Volley发送post请求:


public void postJson() {

    String url = "http://"+host+":8080/web/json.jsp";

    StringRequest postRequest = new StringRequest(

            Request.Method.POST, 

            url,

            new Response.Listener<string>() {

                @Override

                public void onResponse(String response) {

                    // response

                    Log.d("Response", response);

                }

            }, new Response.ErrorListener() {

                @Override

                public void onErrorResponse(VolleyError error) {

                    // error

                    Log.d("Error.Response", error.getMessage());

                }

            }) {

        @Override

        protected Map<string, string=""> getParams() {

            Map<string, string=""> params = new HashMap<string, string="">();

            params.put("username", "xjs");

            params.put("password", "123456");

            return params;

        }

    };

    mQueue.add(postRequest);

}


////////////////////////////////////////////////////////////////////////////////////////

3 Volley获取网络图片:


public void getImage() {

    String imageUrl = "http://"+host+":8080/web/image.jsp";

    NetworkImageView view = (NetworkImageView) findViewById(R.id.network_image_view);

    view.setDefaultImageResId(android.R.drawable.ic_menu_rotate); 

    view.setErrorImageResId(android.R.drawable.ic_delete); 

    view.setImageUrl(imageUrl, new ImageLoader(mQueue, new BitmapLruCache(1024 * 4)));

}


////////////////////////////////////////////////////////////////////////////////////////

4 Volley发送Https请求,需要修改源码:


protected HttpURLConnection createConnection(URL url) throws IOException {

    if (url.toString().toLowerCase(Locale.CHINA).startsWith("https")) {

        HTTPSTrustManager.allowAllSSL();

    }

    return (HttpURLConnection) url.openConnection();

}

//HTTPSTrustManager.java:

public class HTTPSTrustManager implements X509TrustManager {

    private static TrustManager[] trustManagers;

    private static final X509Certificate[] _AcceptedIssuers = new X509Certificate[] {};

    @Override

    public void checkClientTrusted(

            java.security.cert.X509Certificate[] x509Certificates, String s)

            throws java.security.cert.CertificateException {

        // To change body of implemented methods use File | Settings | File

        // Templates.

    }

    @Override

    public void checkServerTrusted(

            java.security.cert.X509Certificate[] x509Certificates, String s)

            throws java.security.cert.CertificateException {

        // To change body of implemented methods use File | Settings | File

        // Templates.

    }

    public boolean isClientTrusted(X509Certificate[] chain) {

        return true;

    }

    public boolean isServerTrusted(X509Certificate[] chain) {

        return true;

    }

    @Override

    public X509Certificate[] getAcceptedIssuers() {

        return _AcceptedIssuers;

    }

    public static void allowAllSSL() {

        HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {

            @Override

            public boolean verify(String arg0, SSLSession arg1) {

                // TODO Auto-generated method stub

                return true;

            }

        });

        SSLContext context = null;

        if (trustManagers == null) {

            trustManagers = new TrustManager[] { new HTTPSTrustManager() };

        }

        try {

            context = SSLContext.getInstance("TLS");

            context.init(null, trustManagers, new SecureRandom());

        } catch (NoSuchAlgorithmException e) {

            e.printStackTrace();

        } catch (KeyManagementException e) {

            e.printStackTrace();

        }

        HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory());

    }

}


////////////////////////////////////////////////////////////////////////////////////////

5 Volley获取服务端返回的cookie,需要修改源码:


@Override

public HttpResponse performRequest(Request<!--?--> request,Map<string, string=""> additionalHeaders) 

    throws IOException,AuthFailureError {

    for (Entry<string, list<string="">> header : connection.getHeaderFields().entrySet()) {

    if (header.getKey() != null) {

        String key = header.getKey();

        List<string> values = header.getValue();

        if(key.equalsIgnoreCase("set-cookie")){

            StringBuilder cookieString = new StringBuilder();

            for(String value : values){

                cookieString.append(value).append("\n");//用\n作为分隔符,cookie中不应该有回车符号

            }

            cookieString.deleteCharAt(cookieString.length() - 1);

            Header h = new BasicHeader(header.getKey(), cookieString.toString());

            response.addHeader(h);

        }else{

            Header h = new BasicHeader(header.getKey(), values.get(0));

            response.addHeader(h);

        }

    }

}

}

//然后再request中重写parseNetworkResponse():

@Override

protected Response<string> parseNetworkResponse(NetworkResponse response) {

    Response<string> superResponse = super.parseNetworkResponse(response);

    Map<string, string=""> responseHeaders = response.headers;

    String rawCookies = responseHeaders.get("Set-Cookie");

    //服务端返回是 set-cookie:JSESSIONID=D90B58454550B4D37C4B66A76BF27B93; Path=/otn BIGipServerotn=2564030730.64545.0000; path=/

    String part1 = substring(rawCookies, "", ";");

    String part2 = substring(rawCookies, "\n", ";");

    //客户端需要的是 cookie:JSESSIONID=D90B58454550B4D37C4B66A76BF27B93; BIGipServerotn=2564030730.64545.0000;

    cookies = part1 + "; " + part2 + ";";

    return superResponse;

}



////////////////////////////////////////////////////////////////////////////////////////

6 Volley发请求的时候上传cookie,在request中重写getHeaders():


@Override

public Map<string, string="">getHeaders() throws AuthFailureError {

         if(cookies!= null && cookies.length() > 0){

                   HashMap<string,string>         headers = newHashMap<string, string="">();

                   headers.put("Cookie",cookies);

                   returnheaders;

         }

         returnsuper.getHeaders();

}


////////////////////////////////////////////////////////////////////////////////////////

7 Volley自定义request:

public class ByteArrayRequest extends Request<byte[]>{

    private final Listener<byte[]> mListener;

    public ByteArrayRequest(int method, String url, Listener<byte[]> listener, ErrorListener errlistener) {

        super(method, url, errlistener);

        mListener = listener;

    }

    @Override

    protected Response<byte[]> parseNetworkResponse(NetworkResponse response) {

        if(response == null){

            return null;

        }

        if(response.statusCode != HttpStatus.SC_OK){

            return null;

        }

        byte[] bytes = response.data;

        return Response.success(bytes, null);

    }

    @Override

    protected void deliverResponse(byte[] response) {

        if(mListener != null){

            mListener.onResponse(response);

        }

    }

}



////////////////////////////////////////////////////////////////////////////////////////

8 Volley设置请求超时时间:

@Override

public RetryPolicy getRetryPolicy() { 

         RetryPolicyretryPolicy = new DefaultRetryPolicy(5000,DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT); 

         returnretryPolicy; 

}


//////////////////////////////////////////////////////////////////////////////////////////////

附一个登陆铁道部12306的例子,源码在:http://download.csdn.net/download/goldenfish1919/7029907

Ps:我在测试的时候用了本地的一个tomcat,一块打包放在了asserts下面。

参考:

http://blog.csdn.net/xyz_lmn/article/details/12165391

http://blog.csdn.net/xyz_lmn/article/details/12746581

http://blog.csdn.net/xyz_lmn/article/details/12177005

http://www.itsalif.info/content/android-volley-tutorial-http-get-post-put

概述:http://blog.csdn.net/t12x3456/article/details/9221611

入门: http://blog.csdn.net/ttdevs/article/details/17566795

自定义request: http://blog.csdn.net/ttdevs/article/details/17586205

源码分析:http://blog.csdn.net/ttdevs/article/details/17764351

发送https请求:http://blog.csdn.net/llwdslal/article/details/18052723

构造cache:http://stackoverflow.com/questions/16682595/android-volley-imageloader-bitmaplrucache-parameter

解析服务端cookie:http://stackoverflow.com/questions/20702178/android-volley-access-http-response-header-fields,http://blog.csdn.net/hpb21/article/details/12163371

上传cookie:http://stackoverflow.com/questions/17049473/how-to-set-custom-header-in-volley-request

设置超时:http://stackoverflow.com/questions/17094718/android-volley-timeout

http://blog.csdn.net/dacainiao007/article/details/12617747,这里关于超时时间增长的因子的说法不准确,应该是当第一次连接超时以后,第二次超时时间会变为原来的多少倍,连接超时和读取超时设置为同一个数。



/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

 在android中基于http请求的框架很多,自己如果比较了解http请求流程,自己也可以写一个不错的框架,由于一些原因,项目中我们自己开发的框架被要求用volley替换掉了,因此我不得不对volley这个开发包进行自己的研究,以希望能够熟悉整个流程,以及能够顺利的将这个开源包融入到项目中同时不会影响原有逻辑。(个人风格的原因吧,我不是很喜欢贴大段大段的代码在帖子里面,大家如果能对照volley源码来看这个帖子的话,会更有收获的)

      

       首先啰嗦些自己对android的http请求框架的一些感悟,如果有不对的地方大家尽情拍砖拍死我吧(就算死了我也要发帖子)。

      

       我理解的基于网络的应用最核心的其实就是request跟response的分发。这个分发机制写好了,框架够健壮,扩展性高,那么以后涉及到这个层次的改动就少(因为从一开始我们的设计都是比较初级的,会随着需求的不断增多而出现一些需要对框架机制的改动需求),因为对于分发机制的改动是很核心的,说牵一发而动全身一点也不为过,稍微改一点点都会对项目有很大的影响甚至是未知的影响,而且构建得不好的话,有些需求的改动会非常麻烦,而这些改动如果是良好的构架的话往往是可以避免的,所以,在初期能够构建好一些是很有必要的。我大概看过一些开源的项目以及这些年来自己做过的项目(没做过游戏,所以游戏的我不知道哈),感觉基于网络的应用要么用http要么用套接字,如果不需要推送的,一般都是使用http来做。


       http的请求步骤大概分为这么几步,就我看来:

       1)发起request,这里的发起者要是个context之类的(一般是activity或者service)东东,当然很多时候发起者也是最后数据的接受者。不同的框架对于这个发起的机制实现各不相同,但总的说来都是统一给出一个公共接口,让发起者封装好必要的信息,使用公共接口,让其实现类去启动实际的http请求操作,大概主要区别在于如何封装这些request信息。

       

       2)进行request请求,并获取response。真正的请求和响应就在这里完成,这里可能有两个需要考虑到的,一个是线程的阻塞,有的框架会让线程阻塞直到获取到响应为止,有的框架则会在这里分发出多个线程,以避免这种阻塞,当然大多数都会采用后者了。二个就是数据的存储,有些固定的请求,比如一些不会轻易变动的信息,在第一次请求到了之后就不需要再多次请求了,一般也可以在这个部分完成这个功能。但总而言之,不管你线程分配也好,使用本地数据也好,还是你的请求出问题了也好,总之你必须在一定的时间内,给我的request一个response。

      

       3)分派response,我们去餐馆吃饭都知道,哪桌点的菜就端到哪桌去,不能端错了。谁发出的request,最后就要给到他的接受者手里,不能给错了。有些框架是靠一些接口类的注入来保证数据的正确接受,有些框架是靠一个寻找机制来保障的(比如广播)。


       //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

     这个大牛对volley的一个感性理解:

       好了,说了这么多我们来看看volley吧。前面那么多铺垫也不是白用的,我就按照我理解的这三步来拆析volley框架。

      1)发起request:volley使用Request抽象类来封装请求。Request类也是整个volley项目中最核心的类(还真没有之一)。从源码我们可以看到,Request的实现类有好几种,而这些实现类有个共同的特点就是他们其实已经定义好了response返回的数据类型,也就是说,其实这里的Requst类并不单单只做request,他们也负责对response的数据处理(当然直接使用实现类的话,我们一般不管这些数据如何被处理的),我们可以自己写实现类并实现其中的数据处理方法

         abstract protected Response<T> parseNetworkResponse(NetworkResponse response);

         来将返回数据变成我们想要的类型,然后由我们再来进一步加工处理。

         Request可不单单只做了这么一件事情。为了证明他为什么是最核心的类,我再列举几个他做了的貌似跟他不相关的事情。

         abstract protected void deliverResponse(T response);

         public void deliverError(VolleyError error) 

         有木有震惊的赶脚,是的,最后response以及error的分发的实际执行者也是Request。所以这个Request类是贯穿一个请求到响应过程自始至终的类。这个其实不难理解,最后一步的分派工作需要一定的信息来保证分派的正确性,而最能提供这些信息的,其实就是最初我们发出的request了。

         简单的介绍下Request如何使用:

         从源码可以看出

            getUrl 是返回的 url地址,

            getBody是返回的请求参数,这两个方法是在http的实际请求中肯定要用到的,使用get请求的话是需要保证getUrl的返回值正确即可,而使用post的话还要保证后面一个方法的返回值正确。

            (返回值如何注入就是你们的事情了,构造函数注入也可,set 方法注入也可)

            这里需要给大家注意的地方原生态的Stringrequest 没有重写 getBody 方法,也就是说 getBody 返回为null,那么 volley将默认使用get请求,如果大家想用post请求并使用Stringrequest的话,请重写这个方法。

          另外还有两个很重要的类,请大家在构造request的时候务必要注入,

          ErrorListener 和 Listener,一个是用来处理error(public void onErrorResponse(VolleyError error))的,一个是用来处理正常返回的(public void onResponse(T response))这两个接口的定义都在Response类中。不难想出上面我所说的两个方法abstract protected void deliverResponse(T response)和public void deliverError(VolleyError error) 的实现其实就是调用这两个接口各自的方法就可以了。

          有些附加的条件我们可以酌情的考虑是否需要实现。

          public String getCacheKey(),CacheKey是volley从Request获取的用于本地存储请求数据的键值,相信大家很快能明白,如果两个request的这个方法返回的值一样的话,后者将能够有机会取到前者存储在本地的数据,从而减少了网络请求。原生态的Request是使用url为cechekey,这样并不一定科学,有本地存储需求的童鞋,请切记重写此方法。当然前提是保证 public final boolean shouldCache()返回为true。否则前功尽弃。

           public void setRetryPolicy(RetryPolicy retryPolicy),从字面意思就可以看出,这个是对一个request的重新请求策略的设置,不同的项目是否需要重新请求,重新请求几次,请求超时的时间,这些就在这设置到里面。一般放就是继承RetryPolicy 类,根据自己的需求实现父类方法。

          不知不觉写了这么多,先写到这里吧,后面我再介绍volley如何实现第二步跟第三步。


本文转载自:http://www.2cto.com/kf/201403/285209.html

新年
粉丝 7
博文 84
码字总数 46086
作品 0
海淀
程序员
私信 提问
Android 网络开发框架的选择

当我们开发企业级应用的时候,一般都会选择使用已经封装好的http框架。开源的比较流行的有: 1、volley 2、android-async-http 3、retrofit 4、okhttp 5、androidquery 6、AndroidAsync 等。...

jdroid
2014/04/20
4.4K
2
修改源码,使volley框架下支持发送和读取cookie

本文为原创,转载请注明出处,否则将依法追究版权 修改源码,让不支持cookie发送的volley框架支持cookie 我们平时开发android应用都需要用到网络技术,通常采用http协议来发起请求并接受网络...

刘小米
2014/12/29
10.3K
11
网络请求框架---Volley

去年的Google I/O大会为android开发者带来了一个网络请求框架,它的名字叫做Volley。Volley诞生的使命就是让Android的网络请求更快,更健壮,而且它的网络通信的实现是基于HttpURLConnection...

Jack_1900
2014/08/01
6.1K
2
Android 网络通信框架Volley简介(Google IO 2013)

什么是Volley 在这之前,我们在程序中需要和网络通信的时候,大体使用的东西莫过于AsyncTaskLoader,HttpURLConnection,AsyncTask,HTTPClient(Apache)等,今年的Google I/O 2013上,Vol...

mingxun
2013/11/06
64
0
Android 网络通信框架Volley简介(Google IO 2013)

什么是Volley 在这之前,我们在程序中需要和网络通信的时候,大体使用的东西莫过于AsyncTaskLoader,HttpURLConnection,AsyncTask,HTTPClient(Apache)等,今年的Google I/O 2013上,Vol...

亭子happy
2013/10/21
447
1

没有更多内容

加载失败,请刷新页面

加载更多

在Ignite中自定义身份认证安全插件

Ignite集群搭建完成之后,应用就可以接入集群进行各种操作了,但是默认的集群,没有安全保护机制,任何应用、支持JDBC的客户端,只要知道集群节点的IP地址,都可以接入集群,这造成了一定的安...

李玉珏
15分钟前
11
0
浅谈proxy代理模式

一、前言 代理是代替服务器去接受请求者的请求的中间人。我们也听说过代理服务器,它的作用的帮助客户端去请求客户端想要的资源,为什么要通过代理呢,那是因为客户端直接访问服务器会被拒绝...

青衣霓裳
16分钟前
2
0
Java多线程之原子操作类

在并发编程中很容易出现并发安全问题,最简单的例子就是多线程更新变量i=1,多个线程执行i++操作,就有可能获取不到正确的值,而这个问题,最常用的方法是通过Synchronized进行控制来达到线程...

全菜工程师小辉
26分钟前
3
0
arcgis arcpy 克里金插值 掩膜 配置符号系统 自动生成图片

整体思路,最后要加载到mxd文件中,然后导出图片 首先加载mxd文件 mxd = mapping.MapDocument(r"./11.mxd") 然后读取数据 并加载到图层中 sr = arcpy.SpatialReference(4326) # 读取csv...

可达鸭Go
今天
4
0
漂亮有创意的思维导图模板分享

相信很多人使用在绘制思维导图时很喜欢使用模板进行编辑,它能够让你在短时间内快速创造出一个风格明显好看的思维导图,对绘制时间以及使用够感受影响都是较为深刻的,下面为大家分享几款漂亮...

干货趣分享
今天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部