zoukankan      html  css  js  c++  java
  • [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();
    }
    };
    }
  • 相关阅读:
    FFmpeg之cmdutils.h源码
    iOS文件操作一览
    ffmpeg结构体SpecifierOpt说明文档
    主要流媒体协议介绍
    HTTP Live Streaming直播(iOS直播)技术分析与实现(转)
    XCode快捷键总结
    ALAssetsLibrary获取相册列表
    iOS教程之ASIHttpRequest(源自51CTO.com)
    libxml/tree.h not found(XCode 4.5&5.1解决方案)
    MyBatis——Log4J(日志)
  • 原文地址:https://www.cnblogs.com/spec-dog/p/3821196.html
Copyright © 2011-2022 走看看