首页 > 代码库 > [Android]Volley源码分析(一)

[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 instances16     } 17 18     /**19      * @param context 应用程序上下文20      */21     public static void init(Context context) {22         mRequestQueue = Volley.newRequestQueue(context);23     }24 25     /**26      * @return27      *         请求队列28      * @throws29      *         IllegalStatException if init has not yet been called30      */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 response17      */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 method29      *         Request type.. Method.GET etc30      * @param url31      *         path for the requests32      * @param requestBody33      *         Q type instance as request body, if no request body needed set it to null34      * @param responseClass35      *         expected class type for the response. Used by gson for serialization.36      * @param listener37      *         handler for the response38      * @param errorListener39      *         handler for errors40      */41     public MyGsonRequest(int method42                         , String url                        43                         , Object requestBody44                         , Class<T> responseClass45                         , Listener<T> listener46                         , 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     @Override57     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     @Override70     protected void deliverResponse(T response) {71         mListener.onResponse(response);72     }73     74     @Override75     public String getBodyContentType() {76         return PROTOCOL_CONTENT_TYPE;77     }78 79     @Override80     public byte[] getBody() {81         try {82             return mRequestBody == null ? null : mGson.toJson(mRequestBody).getBytes(PROTOCOL_CHARSET);83         } catch (UnsupportedEncodingException uee) {            84             VolleyLog85                     .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 one rrorResponse(VolleyError error) {
if (mProgressDialog != null) {
mProgressDialog.dismiss();
}
Toast.makeText(
RegisterActivity.this,
VolleyErrorUtil.getMessage(error, RegisterActivity.this),
Toast.LENGTH_SHORT).show();
}
};
}