[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();
}
};
}