android开发,volley的二次封装和使用

来源:互联网 发布:js a标签target 编辑:程序博客网 时间:2024/05/22 04:48

先简单介绍一下。Android SDK中提供了HttpClient 和 HttpUrlConnection两种方式用来处理网络操作,但应用起来比较繁琐,需要我们编写大量的代码处理很多东西:缓存,Header等等;

而Volley框架就是为解决这些而生的,它与2013年Google I/O大会上被提出:使得Android应用网络操作更方便更快捷;抽象了底层Http Client等实现的细节,让开发者更专注与产生RESTful Request。另外,Volley在不同的线程上异步执行所有请求而避免了阻塞主线程。

这里写图片描述

Volley到底有哪些特点呢?

  1. 自动调度网络请求
  2. 多个并发的网络连接
  3. 通过使用标准的HTTP缓存机制保持磁盘和内存响应的一致
  4. 支持请求优先级
  5. 支持取消请求的强大API,可以取消单个请求或多个
  6. 易于定制
  7. 健壮性:便于正确的更新UI和获取数据
  8. 包含调试和追踪工具

好,废话结束了。一起看看怎么使用volley吧。volley本身使用是比较容易的,但我们做项目过程中往往需要再封装一下,以便于更好的统一使用,本文就是对volley的二次封装,便于开发过程中调用。你也可以根据你的需要进行一些改造。需要注意一点的是,volley只适合数据量比较小,比较频繁的请求。对数据量比较大的,比如下载文件等不太合适。


首先使用volley需要导入相关的jar包,只需要一个jar而已,可以到maven下载:http://mvnrepository.com/artifact/com.mcxiaoke.volley/library/1.0.19


在你的android工程的  values/strings.xml 文件添加下面几个元素,是用来提示用的:

  <string name="no_internet">无网络连接~!</string>    <string name="generic_server_down">连接服务器失败~!</string>    <string name="generic_error">网络异常,请稍后再试~!</string>

下面看看3个关键的类,直接放到工程里面就可以使用,里面有详细的注释

Volley异常帮助类  

package com.kokjuis.travel.volley;import java.util.HashMap;import java.util.Map;import android.content.Context;import com.android.volley.AuthFailureError;import com.android.volley.NetworkError;import com.android.volley.NetworkResponse;import com.android.volley.NoConnectionError;import com.android.volley.ServerError;import com.android.volley.TimeoutError;import com.android.volley.VolleyError;import com.google.gson.Gson;import com.google.gson.reflect.TypeToken;import com.kokjuis.travel.R;//以下是Volley的异常列表://AuthFailureError:如果在做一个HTTP的身份验证,可能会发生这个错误。//NetworkError:Socket关闭,服务器宕机,DNS错误都会产生这个错误。//NoConnectionError:和NetworkError类似,这个是客户端没有网络连接。//ParseError:在使用JsonObjectRequest或JsonArrayRequest时,如果接收到的JSON是畸形,会产生异常。//SERVERERROR:服务器的响应的一个错误,最有可能的4xx或5xx HTTP状态代码。//TimeoutError:Socket超时,服务器太忙或网络延迟会产生这个异常。默认情况下,Volley的超时时间为2.5秒。如果得到这个错误可以使用RetryPolicy。/** * volley异常帮助类 * * @author:gj * @date: 2016/5/17 * @time: 15:05 **/public class VolleyErrorHelper {    /**     * Returns appropriate message which is to be displayed to the user against     * the specified error object.     *     * @param error     * @param context     * @return     */    public static String getMessage(Object error, Context context) {        if (error instanceof TimeoutError) {            return context.getResources().getString(                    R.string.generic_server_down);        } else if (isServerProblem(error)) {            return handleServerError(error, context);        } else if (isNetworkProblem(error)) {            return context.getResources().getString(R.string.no_internet);        }        return context.getResources().getString(R.string.generic_error);    }    /**     * Determines whether the error is related to network     *     * @param error     * @return     */    private static boolean isNetworkProblem(Object error) {        return (error instanceof NetworkError)                || (error instanceof NoConnectionError);    }    /**     * Determines whether the error is related to server     *     * @param error     * @return     */    private static boolean isServerProblem(Object error) {        return (error instanceof ServerError)                || (error instanceof AuthFailureError);    }    /**     * Handles the server error, tries to determine whether to show a stock     * message or to show a message retrieved from the server.     *     * @param err     * @param context     * @return     */    private static String handleServerError(Object err, Context context) {        VolleyError error = (VolleyError) err;        NetworkResponse response = error.networkResponse;        if (response != null) {            switch (response.statusCode) {                case 404:                case 422:                case 401:                    try {                        // server might return error like this { "error":                        // "Some error occured" }                        // Use "Gson" to parse the result                        HashMap<String, String> result = new Gson().fromJson(                                new String(response.data),                                new TypeToken<Map<String, String>>() {                                }.getType());                        if (result != null && result.containsKey("error")) {                            return result.get("error");                        }                    } catch (Exception e) {                        e.printStackTrace();                    }                    // invalid request                    return error.getMessage();                default:                    return context.getResources().getString(                            R.string.generic_server_down);            }        }        return context.getResources().getString(R.string.generic_error);    }}


volley请求类

package com.kokjuis.travel.volley;import android.util.Log;import com.android.volley.AuthFailureError;import com.android.volley.DefaultRetryPolicy;import com.android.volley.NetworkResponse;import com.android.volley.ParseError;import com.android.volley.Request;import com.android.volley.Response;import com.android.volley.Response.Listener;import com.android.volley.RetryPolicy;import com.android.volley.toolbox.HttpHeaderParser;import com.kokjuis.travel.comm.MyApplication;import com.kokjuis.travel.utils.GsonUtil;import com.kokjuis.travel.utils.RsaEncryptUtil;import java.io.UnsupportedEncodingException;import java.net.URLEncoder;import java.util.HashMap;import java.util.Map;/** * 类描述: 创建人:kokJuis 创建时间:2016/3/8 14:07 修改备注: * <p> * VolleyRequest vr=new VolleyRequest(Request.Method.POST, * WebLinksUtil.login,params,new Response.Listener() { * * @Override public void onResponse(Object o) { * <p> * Log.v("--->>>>-----",o.toString()); } }, new * Response.ErrorListener() { * @Override public void onErrorResponse(VolleyError volleyError) { * Log.v("--->>>>-----",volleyError.getMessage()); } }); * <p> * VolleyUtil.getVolleyUtil(this).addToRequestQueue(vr,TAG); */public class VolleyRequest extends Request<String> {    private static final String TAG = "VolleyRequest";    //请求监听    private final Listener<Object> listener;    //保存请求参数    private static Map<String, String> params;    // 构造方法    private VolleyRequest(int method, String url,                          Response.Listener<Object> listener,                          Response.ErrorListener errorListener) {        super(method, url, errorListener);        this.listener = listener;    }    /**     * post请求     *     * @author:gj     * @date: 2016/5/17     * @time: 15:13     **/    public static VolleyRequest post(String url, Map<String, String> params,                                     Response.Listener<Object> listener,                                     Response.ErrorListener errorListener) {        //下面只是打印出完整的URL,便于调试        if (params != null) {            Log.v(TAG, "params:" + params);            String str = "";            for (Map.Entry<String, String> entry : params.entrySet()) {                str += entry.getKey() + "=" + entry.getValue() + "&";            }            String tmp = url + "?"                    + str.substring(0, str.length()-1);            Log.v(TAG, "url:" + tmp);                           //把参数赋值                VolleyRequest.params = data;                    }        return new VolleyRequest(Method.POST, url, listener, errorListener);    }    /**     * get请求     *     * @author:gj     * @date: 2016/5/17     * @time: 15:13     **/    public static VolleyRequest get(String url, Map<String, String> params,                                    Response.Listener<Object> listener,                                    Response.ErrorListener errorListener) {        //下面只是打印出完整的URL,便于调试        if (params != null) {            Log.v(TAG, "params:" + params);            String str = "";            for (Map.Entry<String, String> entry : params.entrySet()) {                str += entry.getKey() + "=" + entry.getValue() + "&";            }            url += "?"                    + str.substring(0, str.length()-1);            Log.v(TAG, "url:" + url);          //这里可以根据你的要求改造        }        return new VolleyRequest(Method.GET, url, listener, errorListener);    }    /**     * 请求返回     *     * @author:gj     * @date: 2017/5/17     * @time: 15:24     **/    @Override    protected Response<String> parseNetworkResponse(            NetworkResponse networkResponse) {        String parsed;        try {            //这里可以获取返回的header信息,可以把想要的东西提取            Map<String, String> responseHeaders = networkResponse.headers;            String Token = responseHeaders.get("Token");            if (Token != null) {                Log.v(TAG, "Token:" + Token);            }            parsed = new String(networkResponse.data,                    HttpHeaderParser.parseCharset(networkResponse.headers));            return Response.success(parsed,                    HttpHeaderParser.parseCacheHeaders(networkResponse));        } catch (UnsupportedEncodingException e) {            // parsed = new String(networkResponse.data);            return Response.error(new ParseError(e));        } catch (Exception e) {            return Response.error(new ParseError(e));        }    }    /**     * 监听返回     *     * @author:gj     * @date: 2017/5/17     * @time: 15:20     **/    @Override    protected void deliverResponse(String response) {        listener.onResponse(response);    }    /**     * 请求设置参数     *     * @author:gj     * @date: 2017/5/17     * @time: 15:20     **/    @Override    protected Map<String, String> getParams() throws AuthFailureError {        return params == null ? super.getParams() : params;    }    /**     * 设置请求头     *     * @author:gj     * @date: 2017/5/17     * @time: 15:20     **/    @Override    public Map<String, String> getHeaders() throws AuthFailureError {        //在这个方法里面,可以设置请求头的参数,比如Charset,Content-Type,也可以设置一些你想要的值        HashMap<String, String> localHashMap = new HashMap<String, String>();        localHashMap.put("Charset", "UTF-8");        localHashMap.put("Content-Type", "application/x-www-form-urlencoded");        // localHashMap.put("Accept-Encoding", "gzip,deflate");        //设置请求的token        localHashMap.put("Token", "");        return localHashMap;    }    /**     * 设置请求超时时间     *     * @author:gj     * @date: 2017/5/17     * @time: 15:22     **/    @Override    public RetryPolicy getRetryPolicy() {        // 设置超时时间为5秒。        RetryPolicy retryPolicy = new DefaultRetryPolicy(5000, 0,                DefaultRetryPolicy.DEFAULT_BACKOFF_MULT);        return retryPolicy;    }    @Override    public void setRetryPolicy(RetryPolicy retryPolicy) {        RetryPolicy Policy = new DefaultRetryPolicy(5000, 0,                DefaultRetryPolicy.DEFAULT_BACKOFF_MULT);        super.setRetryPolicy(Policy);    }}


volley请求工具类

package com.kokjuis.travel.volley;import android.content.Context;import android.graphics.Bitmap;import android.text.TextUtils;import android.util.LruCache;import com.android.volley.Request;import com.android.volley.RequestQueue;import com.android.volley.toolbox.ImageLoader;import com.android.volley.toolbox.Volley;/** * 创建人:kokJuis 创建时间:2016/3/8 14:57 备注: */public class VolleyUtil {    public static final String TAG = "VolleyUtil";    private static VolleyUtil volleyUti;    private RequestQueue mRequestQueue;    private ImageLoader mImageLoader;    private Context mContext;    /**     * 单例模式。     *     * @param context     */    private VolleyUtil(Context context) {        this.mContext = context;        mRequestQueue = getRequestQueue();        mImageLoader = new ImageLoader(mRequestQueue,                new ImageLoader.ImageCache() {                    private final LruCache<String, Bitmap> cache = new LruCache<String, Bitmap>(                            20);                    @Override                    public Bitmap getBitmap(String url) {                        return cache.get(url);                    }                    @Override                    public void putBitmap(String url, Bitmap bitmap) {                        cache.put(url, bitmap);                    }                });    }    public static synchronized VolleyUtil getVolleyUtil(Context context) {        if (volleyUti == null) {            volleyUti = new VolleyUtil(context);        }        return volleyUti;    }    // 获取一个请求队列    public RequestQueue getRequestQueue() {        if (mRequestQueue == null) {            mRequestQueue = Volley.newRequestQueue(mContext                    .getApplicationContext());        }        return mRequestQueue;    }    // 把请求添加到队列里面    public <T> void addToRequestQueue(Request<T> req, String tag) {        // 设置一个标记,便于取消队列里的请求        req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);        getRequestQueue().add(req);    }    // 取消指定请求    public void cancelRequest(String tag) {        if (mRequestQueue != null) {            mRequestQueue.cancelAll(tag);        }    }    public ImageLoader getImageLoader() {        return mImageLoader;    }}


使用:

 private void getUserData(String account) {        Map<String, String> params = new HashMap<String, String>();        params.put("account", account);//创建一个get请求        VolleyRequest vr = VolleyRequest.get(                ApiList.findByAccounts_api, params,                new Listener<Object>() {                    @Override                    public void onResponse(Object arg0) {                        if (arg0 != null) {//请求成功                            Log.v(TAG, arg0.toString());                        }                    }                }, new ErrorListener() {                    @Override                    public void onErrorResponse(VolleyError arg0) {                        Log.e(TAG, arg0.getMessage());//请求失败,打印失败信息                    }                });//把请求添加到请求队列才会真正的请求网络,第一参数就是创建的请求,第二个是请求的标记,可以通过这个标记取消请求        VolleyUtil.getVolleyUtil(this).addToRequestQueue(vr, TAG);    }    @Override    protected void onDestroy() {        super.onDestroy();//取消请求        VolleyUtil.getVolleyUtil(this).cancelRequest(TAG);    }