封装一个在小项目中使用的volley(通俗简便、方便灵活)

来源:互联网 发布:卡西欧计算器软件 编辑:程序博客网 时间:2024/05/16 10:05

Google 2013 I/O大会上发布了Android平台上的网络通信库volley,今天Google 2017 I/O大会正在进行中,封装个小volley做个纪念(主要是以后可以在小项目中直接使用)。

volley的设计目标是非常适合去进行数据量不大,但通信频繁的网络操作,而对于大数据量的网络操作,比如说下载文件等,volley的表现会非常的糟糕,根据项目的实际情况选择使用。

volley整体框架类的继承结构图:

其实封装的已经很好了,非常方便我们使用,无论是请求字符串还是图片都很简单。volley最简单直接的使用分为三步,这里以StringRequest为例演示一下:

private void performStringRequest() {        /**         * volley请求的三部曲:         * 1 . 创建请求         * 2 . 创建请求队列         * 3 . 将请求添加到请求队列中         */        String url = "https://www.baidu.com/";        Response.Listener<String> listener = new Response.Listener<String>() {            @Override            public void onResponse(String response) {                // 请求成功的结果处理,请求结果在response中                Log.d(TAG, "onResponse: " + response);            }        };        Response.ErrorListener errorListener = new Response.ErrorListener() {            @Override            public void onErrorResponse(VolleyError error) {                // 请求发生错误的回调                Log.d(TAG, "onErrorResponse: " + error.getMessage());            }        };        //get请求:三参数,url , 请求成功监听和错误监听        StringRequest stringRequest = new StringRequest(url, listener, errorListener);//1 . 创建请求        RequestQueue queue = Volley.newRequestQueue(getApplicationContext());//2 . 创建请求队列        queue.add(stringRequest);//3 . 将请求添加到请求队列中}
上面是StringRequest的get请求,post请求也比较简单,只是创建请求的时候指定请求类型,传递请求体参数即可,其它步骤同get请求:
new StringRequest(Request.Method.POST, url, listener, errorListener) {            @Override            protected Map<String, String> getParams() throws AuthFailureError {                Map<String, String> map = new HashMap<String, String>();                map.put("params1", "values1");//传的参数1                map.put("params2", "values2");//传的参数2                return map;            }};//1 . 创建post请求,2,3同get请求(略)
这只是以StringRequest为例简单介绍了volley的使用,其它几个兄弟类的使用方式与其类似,这里就不一一举例了。

每次这么做代码量会比较多,而且每做一次请求就创建一个请求队列RequestQueue明显是不合理的,接下来稍微封装一下,方面日后小项目的使用:
模仿StringRequest封装一个自己的Request请求类,可以直接进行get或者post请求

public class QJRequest<T> extends Request<T> {    private Class<T> mClass;    private Gson mGson;    private Response.Listener<T> mListener;    private Map<String, String> requestBodyMap;//post 请求 请求体参数集合    /**     * POST 请求     *     * @param clazz         请求结果要解析成的java bean     * @param url     * @param map           请求体参数     * @param listener     * @param errorListener     */    public QJRequest(Class<T> clazz, String url, Map<String, String> map, Response.Listener listener, Response.ErrorListener errorListener) {        super(Method.POST, url, errorListener);        mClass = clazz;        mListener = listener;//模仿StringRequest的做法        requestBodyMap = map;    }    /**     * GET 请求     *     * @param url           请求的url     * @param listener      成功的监听     * @param errorListener 失败的监听     */    public QJRequest(Class<T> clazz, String url, Response.Listener listener, Response.ErrorListener errorListener) {        super(Method.GET, url, errorListener);        mClass = clazz;        mListener = listener;//模仿StringRequest的做法    }    @Override    protected Response parseNetworkResponse(NetworkResponse networkResponse) {        byte[] data = networkResponse.data;//请求成功后得到的byte数组        // 使用 Gson解析        try {            String result = new String(data, "utf-8");//使用utf-8防止乱码问题            T bean = getGson().fromJson(result, mClass);            //返回解析后的结果            //第一个参数是解析后的结果(java bean)            //第二个参数是缓存的条目信息            return Response.success(bean, HttpHeaderParser.parseCacheHeaders(networkResponse));        } catch (IOException e) {            e.printStackTrace();            return Response.error(new ParseError(networkResponse));//返回解析错误        }    }    @Override    protected void deliverResponse(T t) {        this.mListener.onResponse(t);    }    /**     * @return post 请求的请求体参数     * @throws AuthFailureError     */    @Override    protected Map<String, String> getParams() throws AuthFailureError {        return requestBodyMap;    }    /**     * @return 一个简单的单例 Gson对象     */    private Gson getGson() {        if (mGson == null) {            mGson = new Gson();        }        return mGson;    }    /**     * 将请求加入到请求队列中     * 创建请求对象之后可以直接调用此方法,链式调用方便代码书写     */    public void execute() {        NetworkManager.addRequest(this);    }}
请求对象我们有了,还需要一个请求队列,我们把这个请求队列封装在网络管理类中
public class NetworkManager {    //整个app只保留和维护一个Volley请求队列    private static RequestQueue mRequestQueue;    //缓存大小是我们运行内存大小的1/4    private static final int CACHE_SIZE = (int) (Runtime.getRuntime().freeMemory() / 4);    //维护一个全局的ImageLoader    private static ImageLoader mImageLoader;//Helper that handles loading and caching images from remote URLs.    /**     * 在application 的onCreate方法中调用此方法     *     * @param context getApplicationContext     */    public static void init(Context context) {        mRequestQueue = Volley.newRequestQueue(context);        mImageLoader = new ImageLoader(mRequestQueue, new MyImageCache(CACHE_SIZE));    }    /**     * 添加请求到请求队列     */    public static void addRequest(Request request) {        mRequestQueue.add(request);    }    /**     * LruCache (Least Recent Use Cache)     *      * 当缓存空间已经满了,就会把最近最少使用的数据清除掉     *     * K 存储数据的键值     * V 存储的数据     */    public static class MyImageCache extends LruCache<String, Bitmap> implements ImageLoader.ImageCache {        /**         * @param maxSize 缓存的大小         */        public MyImageCache(int maxSize) {            super(maxSize);        }        /**         * @return 返回对应数据缓存的大小, 即图片的大小         */        @Override        protected int sizeOf(String key, Bitmap value) {            //return value.getByteCount(); api 要求比较高 , 故用下面的 , 实质相同            return value.getRowBytes() * value.getHeight();        }        /**         * 从缓存里面获取对应url的图片         *         * @param url 缓存的key         */        @Override        public Bitmap getBitmap(String url) {            return get(url);//从lru cache里面获取图片        }        /**         * 把对应url的图片存进缓存         */        @Override        public void putBitmap(String url, Bitmap bitmap) {            put(url, bitmap);        }    }    /**     * @return 全局唯一的ImageLoader     */    public static ImageLoader getImageLoader() {        return mImageLoader;    }}

在应用的Application中还需要初始化我们的NetWorkManager:

public class QJApplication extends Application {    @Override    public void onCreate() {        super.onCreate();        NetworkManager.init(getApplicationContext());    }}

如此简单封装之后我们的请求就可以这么写了:

private void performGetRequest() {        String url = "http://192.168.1.9:8080/version.json";//自己测试的url        Response.Listener<VersionBean> listener = new Response.Listener<VersionBean>() {            @Override            public void onResponse(VersionBean o) {                Log.d(TAG, "onResponse: " + o);            }        };        Response.ErrorListener errorListener = new Response.ErrorListener() {            @Override            public void onErrorResponse(VolleyError volleyError) {                Log.d(TAG, "onErrorResponse: " + volleyError.getMessage());            }        };        new QJRequest(VersionBean.class, url, listener, errorListener).execute();//get请求封装后写法示例}
传入url和成功错误的回调之后我们最后可以得到的是对应json数据的java bean类,这样就方便很多了,post请求亦是如此
private void performPostRequest() {        String url = "http://139.199.76.41:8080/vr-app/game/gameRecommends";        Map<String, String> map = new HashMap<>();        map.put("item", "2");        Response.Listener<GameRecommendsBean> listener = new Response.Listener<GameRecommendsBean>() {            @Override            public void onResponse(GameRecommendsBean o) {                Log.d(TAG, "onResponse: " + o);            }        };        Response.ErrorListener errorListener = new Response.ErrorListener() {            @Override            public void onErrorResponse(VolleyError volleyError) {                Log.d(TAG, "onErrorResponse: " + volleyError.getMessage());            }        };        new QJRequest(GameRecommendsBean.class, url, map, listener, errorListener).execute();}
与get请求相比,post请求只是多了一个请求体参数,需要一个Map集合,创建请求之后调用execute()方法直接发送请求,便于代码的书写
对于图片的请求,volley给我提供了一个用于请求网络图片的ImageView,即NetworkImageView,利用我们的简单封装可以很方便的请求图片

mNetworkImageView.setImageUrl(url, NetworkManager.getImageLoader());//使用NetWorkImageView只需要url即可
简单封装到此结束,谢谢阅读!
封装及使用Demo下载

阅读全文
0 0
原创粉丝点击