[Android]Volley源码分析(一)

一. 如何使用Volley?

1. 首先定义一个RequestManager类,用来在Android程序启动时对Volley进行初始化。RequestManager为单例类,因为只有在程序启动时调用,所以不需要考虑并发问题。

 1 /**
 2  * Manager for the queue
 3  */
 4 public class RequestManager {
 5
 6     /**
 7      * 请求队列
 8      */
 9     private static RequestQueue mRequestQueue;
10
11     /**
12      * 私有化构造函数
13      */
14     private RequestManager() {
15      // no instances
16     }
17
18     /**
19      * @param context 应用程序上下文
20      */
21     public static void init(Context context) {
22         mRequestQueue = Volley.newRequestQueue(context);
23     }
24
25     /**
26      * @return
27      *         请求队列
28      * @throws
29      *         IllegalStatException if init has not yet been called
30      */
31     public static RequestQueue getRequestQueue() {
32         if (mRequestQueue != null) {
33             return mRequestQueue;
34         } else {
35             throw new IllegalStateException("Not initialized");
36         }
37     }
38 }

2. 为了方便对请求的Body(PUT或POST请求时)及响应体进行解析,我们可以继承Volley的Request类,自定义一个通过Gson来解析请求与响应的Request。

 1 /**
 2  * Wrapper for Volley requests to facilitate parsing of json responses.
 3  */
 4 public class MyGsonRequest<T> extends Request<T>{
 5
 6     /** Charset for request. */
 7     private static final String PROTOCOL_CHARSET = "utf-8";
 8     /** Content type for request. */
 9     private static final String PROTOCOL_CONTENT_TYPE =
10         String.format("application/json; charset=%s", PROTOCOL_CHARSET);
11     /**
12      * Gson parser
13      */
14     private final Gson mGson;
15     /**
16      * Class type for the response
17      */
18     private final Class<T> mResponseClass;
19     private final Object mRequestBody;
20
21
22     /**
23      * Callback for response delivery
24      */
25     private final Listener<T> mListener;
26
27     /**
28      * @param method
29      *         Request type.. Method.GET etc
30      * @param url
31      *         path for the requests
32      * @param requestBody
33      *         Q type instance as request body, if no request body needed set it to null
34      * @param responseClass
35      *         expected class type for the response. Used by gson for serialization.
36      * @param listener
37      *         handler for the response
38      * @param errorListener
39      *         handler for errors
40      */
41     public MyGsonRequest(int method
42                         , String url
43                         , Object requestBody
44                         , Class<T> responseClass
45                         , Listener<T> listener
46                         , ErrorListener errorListener) {
47
48         super(method, url, errorListener);
49         this.mRequestBody = requestBody;
50         this.mResponseClass = responseClass;
51         this.mListener = listener;
52         mGson = new Gson();
53
54     }
55
56     @Override
57     protected Response<T> parseNetworkResponse(NetworkResponse response) {
58         try {
59             String json = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
60             return Response.success(mGson.fromJson(json, mResponseClass),
61                     HttpHeaderParser.parseCacheHeaders(response));
62         } catch (UnsupportedEncodingException e) {
63             return Response.error(new ParseError(e));
64         } catch (JsonSyntaxException e) {
65             return Response.error(new ParseError(e));
66         }
67     }
68
69     @Override
70     protected void deliverResponse(T response) {
71         mListener.onResponse(response);
72     }
73
74     @Override
75     public String getBodyContentType() {
76         return PROTOCOL_CONTENT_TYPE;
77     }
78
79     @Override
80     public byte[] getBody() {
81         try {
82             return mRequestBody == null ? null : mGson.toJson(mRequestBody).getBytes(PROTOCOL_CHARSET);
83         } catch (UnsupportedEncodingException uee) {
84             VolleyLog
85                     .wtf("Unsupported Encoding while trying to get the bytes of %s using %s",
86                             mGson.toJson(mRequestBody), PROTOCOL_CHARSET);
87             return null;
88         }
89     }
90 }

需要重写Request的以下方法:

1). parseNetworkResponse  通过Gson将服务器返回的Json字符串解析为你想要的对象 mGson.fromJson(json, mResponseClass)

2). deliverResponse  调用你自定义的实现了Response.Listener接口的回调方法onResponse

3). getBodyContentType  获取请求体的内容类型,如json类型,编码为utf-8

4). getBody 获取请求体的字节数组表示。 同样是通过Gson将你的请求体中对象转换为Json字符串来获取字节数组 mGson.toJson(mRequestBody).getBytes(PROTOCOL_CHARSET)

3. 接下来可以针对不同的领域模型定义一些客户端类,比如对用户的一些服务器请求操作可以定义一个UserManager类,实现注册、登录等功能。

public class UserManager {
    public static UserManager getInstance(){
        if(mInstance == null) {
            mInstance = new UserManager();
        }
        return mInstance;
    }

    public void register(Listener<String> listener, ErrorListener errorListener, User user){
        Uri.Builder uriBuilder = Uri.parse(USER_BASE_URL).buildUpon();
        String uri = uriBuilder.build().toString();
        MyGsonRequest<String> request = new MyGsonRequest<String>(Method.POST
                , uri
                , user
                , String.class
                , listener
                , errorListener);

        Log.v(TAG, request.toString());
        RequestManager.getRequestQueue().add(request);
    }
}

上述代码实例化了一个request,将这个request加入Volley的请求队列中,由Volley来负责对请求进行调度处理。

3. 然后别忘了在程序的Application类中,对Volley进行初始化

 1 public class MainApplication extends Application {
 2     @Override
 3     public void onCreate() {
 4         super.onCreate();
 5         RequestManager.init(this);
 6         //其他初始化
 7     }
 8     ...
 9 }
10     

4. 最后在具体的Activity中,就可以通过如下方式对服务器发起注册请求了。

//比如点击注册按钮,在onClick方法中调用UserManager.getInstance().register(createLoginSuccessListener(),
                    createLoginErrorListener(), user);//请求成功返回时调用private Listener<String> createRegisterSuccessListener() {	return new Listener<String>() {		@Override		public void onResponse(String response) {			if (mProgressDialog != null) {				mProgressDialog.dismiss();			}			Toast.makeText(				RegisterActivity.this,				getString(R.string.msg_register_success),				Toast.LENGTH_SHORT).show();

			}		};}

//请求失败时调用private Response.ErrorListener createRegisterErrorListener() {	return new Response.ErrorListener() {		@Override		public void onErrorResponse(VolleyError error) {			if (mProgressDialog != null) {				mProgressDialog.dismiss();			}			Toast.makeText(				RegisterActivity.this,				VolleyErrorUtil.getMessage(error, RegisterActivity.this),				Toast.LENGTH_SHORT).show();			}		};}

[Android]Volley源码分析(一)

时间: 2024-08-25 06:36:17

[Android]Volley源码分析(一)的相关文章

[Android]Volley源码分析(四)

上篇中有提到NetworkDispatcher是通过mNetwork(Network类型)来进行网络访问的,现在来看一下关于Network是如何进行网络访问的. Network部分的类图: Network有一个实现类BasicNetwork,它有一个mHttpStack的属性,实际的网络请求是由这个mHttpStack来进行的,看BasicNetwork的performRequest()方法, 1 @Override 2 public NetworkResponse performRequest

[Android]Volley源码分析(二)Cache

Cache作为Volley最为核心的一部分,Volley花了重彩来实现它.本章我们顺着Volley的源码思路往下,来看下Volley对Cache的处理逻辑. 我们回想一下昨天的简单代码,我们的入口是从构造一个Request队列开始的,而我们并不直接调用new来构造,而是将控制权反转给Volley这个静态工厂来构造. com.android.volley.toolbox.Volley: public static RequestQueue newRequestQueue(Context conte

[Android]Volley源码分析(叁)Network

如果各位看官仔细看过我之前的文章,实际上Network这块的只是点小功能的补充.我们来看下NetworkDispatcher的核心处理逻辑: <span style="font-size:18px;">while (true) { try { // Take a request from the queue. request = mQueue.take(); } catch (InterruptedException e) { // We may have been int

[Android]Volley源码分析(肆)应用

通过前面的讲述,相信你已经对Volley的原理有了一定了解.本章将举一些我们能在应用中直接用到的例子,第一个例子是 NetworkImageView类,其实NetworkImageView顾名思义就是将异步的操作封装在了控件本身,这种设计可以充分保留控件的移植性和维护性.NetworkImageView通过调用setImageUrl来指定具体的url: public void setImageUrl(String url, ImageLoader imageLoader) { mUrl = ur

[Android] Volley源码分析(一)体系结构

Volley:google出的一个用于异步处理的框架.由于本身的易用性和良好的api,使得它能得以广泛的应用.我还是一如既往从源码的方向上来把控它.我们先通过一段简单的代码来了解Volley RequestQueue queue = Volley.newRequestQueue(this); ImageRequest imagerequest = new ImageRequest(url, new Response.Listener<Bitmap>(){ @Override public vo

[Android]Volley源码分析(五)

前面几篇通过源码分析了Volley是怎样进行请求调度及请求是如何被实际执行的,这篇最后来看下请求结果是如何交付给请求者的(一般是Android的UI主线程). 类图: 请求结果的交付是通过ResponseDelivery接口完成的,它有一个实现类ExecutorDelivery, 主要有postResponse()与postError()两个方法,分别在请求成功或失败时将结果提交给请求发起者. 1. 首先,在NetworkDispatcher的run()方法中,当服务器返回响应并解析完后,会调用

[Android]Volley源码分析(二)

上一篇介绍了Volley的使用,主要接触了Request与RequestQueue这两个类,这篇就来了解一下这两个类的具体实现. Request类图: Request类: Request是一个抽象类,其中的主要属性: mMethod: 请求方法,目前支持GET, POST, PUT, DELETE, HEAD, OPTIONS,TRACE, PATCH方法 mUrl: 请求Url mErrorListener: 错误处理监听器,请求出错时调用 mSequence: 请求的序号,相同优先级的请求在

[Android] Volley源码分析(五)答疑

Volley源码分析系列出了有一段日子了,有不少看官私底下给我留言,同时抛出了一些问题.对于一些比较简单的问题我们跳过去,这两天接到网友是@smali提出的问题.不得不赞一下这位看官看源码时候的细腻程度,我引出这个问题供大家一块思考一下. Q:在写入文件头数据的时候为何不直接写入Int而是通过移位的方式来完成? 我们来看一下对应的源码: writeInt(os, CACHE_MAGIC); static void writeInt(OutputStream os, int n) throws I

Android Volley源码分析

今天来顺手分析一下谷歌的volley http通信框架.首先从github上 下载volley的源码, 然后新建你自己的工程以后 选择import module 然后选择volley. 最后还需要更改1个 配置文件 就是我选中的那句话.记得要加.不然会报错.把volley作为一个module 在你的项目中引用的原因是,因为我们要分析源码,需要测试我们心中所想.所以这么做是最方便的. 就相当于eclipse里面的工程依赖. 有关于volley 如何使用的教程 我就不在这写了,请自行谷歌,我们直接看