Android网络请求框架Volley学习

来源:互联网 发布:php 策略模式 编辑:程序博客网 时间:2024/05/20 10:55

本文github地址:
https://github.com/YoungBear/MyBlog/blob/master/VolleyLearn.md

Volley是Android下个一个网络请求库,它可以让Android下的网络访问更加简单和快速。默认情况下,Volley都是异步访问网络的,所以我们不必担心异步处理问题。

Volley的优点:

  1. 请求队列和请求优先级
  2. 请求Cache和内存管理
  3. 扩展性性强
  4. 可以取消请求

导入Volley的方法

第一种

在build.gradle中添加dependency:

dependencies {    ...    compile 'com.android.volley:volley:1.0.0'}

第二种

使用源代码,作为一个library project。

git clone https://android.googlesource.com/platform/frameworks/volley

另外,也可以在源代码中导出jar包,使用jar包作为库。

使用Volley进行网络请求

首先,在AndroidManifest.xml中添加网络访问权限,

<uses-permission android:name="android.permission.INTERNET"/>

使用一个单例来管理请求(一般可以继承Application)

//VolleyController.javapublic class VolleyController {    public static final String TAG = VolleyController.class.getSimpleName();    private static volatile VolleyController mInstance;    private RequestQueue mRequestQueue;    private ImageLoader mImageLoader;    private static Context mContext;    private VolleyController(Context context) {        mContext = context.getApplicationContext();        mRequestQueue = Volley.newRequestQueue(mContext);        mImageLoader = new ImageLoader(mRequestQueue, new LruBitmapCache());    }    public static VolleyController getInstance(Context context) {        if (mInstance == null) {            synchronized (VolleyController.class) {                if (mInstance == null) {                    mInstance = new VolleyController(context);                }            }        }        return mInstance;    }    public RequestQueue getRequestQueue() {        return mRequestQueue;    }    public ImageLoader getImageLoader() {        return mImageLoader;    }    public <T> void addToRequestQueue(Request<T> req, String tag) {        req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);        mRequestQueue.add(req);    }    public <T> void addToRequestQueue(Request<T> req) {        req.setTag(TAG);        mRequestQueue.add(req);    }    public void cancelPendingRequests(Object tag) {        if (mRequestQueue != null) {            mRequestQueue.cancelAll(tag);        }    }}

还需要一个Cache来存放请求的图片:

//LruBitmapCache.javapublic class LruBitmapCache extends LruCache<String, Bitmap> implements ImageLoader.ImageCache{    public static int getDefaultLruCacheSize() {        final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);        final int cacheSize = maxMemory / 8;        return cacheSize;    }    public LruBitmapCache() {        this(getDefaultLruCacheSize());    }    public LruBitmapCache(int sizeInKiloBytes) {        super(sizeInKiloBytes);    }    @Override    protected int sizeOf(String key, Bitmap value) {        return value.getRowBytes() * value.getHeight() / 1024;    }    @Override    public Bitmap getBitmap(String url) {        return get(url);    }    @Override    public void putBitmap(String url, Bitmap bitmap) {        put(url, bitmap);    }}

String Request

新建一个Request并且把他加入到请求队列中RequestQueue:

    private void simpleRequest() {        StringRequest stringRequest = new StringRequest(                Request.Method.GET,                TEST_URL,                new Response.Listener<String>() {                    @Override                    public void onResponse(String response) {                        Log.d(TAG, "onResponse, response: " + response);                        txtDisplay.setText("Response is: " + response);                    }                },                new Response.ErrorListener() {                    @Override                    public void onErrorResponse(VolleyError error) {                        Log.d(TAG, "onErrorResponse, error: " + error.getMessage());                        txtDisplay.setText("That didn't work!");                    }                });        VolleyController.getInstance(this).addToRequestQueue(stringRequest, TAG);    }

Volley工作原理图

Life of a request

在Activity的onStop()方法中cancel所有标记为该TAG的请求:

@Overrideprotected void onStop() {    super.onStop();    VolleyController.getInstance(this).cancelPendingRequests(TAG);}

创建POST请求

上面说的都是GET请求,下面来说一下POST请求,与GET请求不同的是,只要在创建请求的时候将请求类型改为POST请求,并且override Request的getParams方法即可。

添加请求头部信息

override Request的getHeaders方法。

    private void simplePostRequest() {        StringRequest stringRequest = new StringRequest(                Request.Method.POST,                TEST_URL,                new Response.Listener<String>() {                    @Override                    public void onResponse(String response) {                        Log.d(TAG, "post, onResponse, response: " + response);                        txtDisplay.setText("Response is: " + response);                    }                },                new Response.ErrorListener() {                    @Override                    public void onErrorResponse(VolleyError error) {                        Log.d(TAG, "post, onErrorResponse, error: " + error.getMessage());                        txtDisplay.setText("That didn't work!");                    }                }        ) {            @Override            protected Map<String, String> getParams() throws AuthFailureError {                Map<String, String> params = new HashMap<String, String>();                params.put("name", "Androidhive");                params.put("email", "abc@androidhive.info");                params.put("password", "password123");                return params;            }            @Override            public Map<String, String> getHeaders() throws AuthFailureError {                HashMap<String, String> headers = new HashMap<String, String>();                headers.put("Content-Type", "application/json");                headers.put("apiKey", "xxxxxxxxxxxxxxx");                return headers;            }        };        //关闭Cache        stringRequest.setShouldCache(false);        VolleyController.getInstance(this).addToRequestQueue(stringRequest, TAG);    }

创建Image请求

Volley库中自带了NetworkImageView类,这个ImageView可以自动使用volley下载图片。

使用ImageRequest

    private void imageRequest() {        ImageRequest imageRequest = new ImageRequest(                TEST_URL_1,                new Response.Listener<Bitmap>() {                    @Override                    public void onResponse(Bitmap response) {                        mImageView.setImageBitmap(response);                    }                }, 0, 0, null,                new Response.ErrorListener() {                    @Override                    public void onErrorResponse(VolleyError error) {                        Log.d(TAG, "onErrorResponse, error: " + error.getMessage());                    }                }        );        VolleyController.getInstance(this).addToRequestQueue(imageRequest, TAG);    }

ImageRequest构造函数源代码:

    @Deprecated    public ImageRequest(String url, Response.Listener<Bitmap> listener, int maxWidth, int maxHeight,            Config decodeConfig, Response.ErrorListener errorListener) {        this(url, listener, maxWidth, maxHeight,                ScaleType.CENTER_INSIDE, decodeConfig, errorListener);    }

可以看到,ImageRequest的构造函数接收6个参数

  1. 第一个参数是图片的URL地址
  2. 第二个参数是图片请求成功的回调,这里我们把返回的Bitmap参数设置到ImageView中
  3. 第三和第四个参数分别用于指定允许图片最大的宽度和高度,如果指定的网络图片的宽度或高度大于这里的最大值,则会对图片进行压缩,指定成0的话就表示不管图片有多大,都不进行压缩。
  4. 第五个参数用于指定图片的颜色属性,Bitmap.Config下的几个常量都可以在这里使用,其中ARGB_8888可以展示最好的颜色属性,每个图片像素占据4个人字节的大小,而RGB_565则表示每个图片像素占据2个字节大小。
  5. 第六个参数是图片请求失败的回调,我们可以在请求失败时显示一张失败的图片。

使用ImageLoader

ImageLoader也可以用于加载网络上的图片,并且它的内部也是使用ImageRequest来实现的,不过ImageLoader明显要比ImageRequest更加高效,因为它不仅可以帮我们对图片进行缓存,还可以过滤掉重复的链接,避免重复发送请求。

由于ImageLoader已经不是继承自Request的了,所以它的用法也和我们之前学到的内容有所不同,总结起来大致可以分为以下四步:

  1. 创建一个RequestQueue对象
  2. 创建一个ImageLoader对象
  3. 获取一个ImageListener对象
  4. 调用ImageLoader的get()方法加载网络上的图片
    private void imageLoaderGet() {        ImageLoader imageLoader = VolleyController.getInstance(this).getImageLoader();        imageLoader.get(TEST_URL_3, new ImageLoader.ImageListener() {            @Override            public void onResponse(ImageLoader.ImageContainer response, boolean isImmediate) {                mImageView3.setImageBitmap(response.getBitmap());            }            @Override            public void onErrorResponse(VolleyError error) {                Log.e(TAG, "Image Load Error: " + error.getMessage());            }        });    }

使用NetworkImageView

NetworkImageView是一个自定义控件,它是继承自ImageView的,具备ImageView控件的所有功能,并且在原生的基础之上加入了加载网络图片的功能。

使用方法:

  1. 在布局文件中添加NetworkImageView
  2. 获取ImageLoader
  3. 调用NetworkImageView的setImageUrl()方法
//...    <com.android.volley.toolbox.NetworkImageView        android:id="@+id/network_img_display"        android:layout_width="wrap_content"        android:layout_height="wrap_content"/>    mNetworkImageView = (NetworkImageView) findViewById(R.id.network_img_display);    private void setNetworkImageView() {        ImageLoader imageLoader = VolleyController.getInstance(this).getImageLoader();        mNetworkImageView.setImageUrl(TEST_URL_2, imageLoader);    }

JSON Request

    private void jsonRequest() {        JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(                Request.Method.GET,                TEST_URL,                null,                new Response.Listener<JSONObject>() {                    @Override                    public void onResponse(JSONObject response) {                        txtDisplay.setText(response.toString());                    }                },                new Response.ErrorListener() {                    @Override                    public void onErrorResponse(VolleyError error) {                        Log.e(TAG, "onErrorResponse, error: " + error.getMessage());                    }                });        VolleyController.getInstance(this).addToRequestQueue(jsonObjectRequest, TAG);    }    private void jsonArrayRequest() {        JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(                Request.Method.GET,                TEST_URL2,                null,                new Response.Listener<JSONArray>() {                    @Override                    public void onResponse(JSONArray response) {                        txtDisplay.setText(response.length() + "\n" + response.toString());                    }                },                new Response.ErrorListener() {                    @Override                    public void onErrorResponse(VolleyError error) {                        Log.e(TAG, "onErrorResponse, error: " + error.getMessage());                    }                }        );        VolleyController.getInstance(this).addToRequestQueue(jsonArrayRequest, TAG);    }

自定义Requet

在build.gradle文件中添加gson依赖:

dependencies {    ...    compile 'com.google.code.gson:gson:2.7'}

自定义GsonRequest:

//GsonRequest.javapublic class GsonRequest<T> extends Request<T> {    private final Gson gson = new Gson();    private final Class<T> clazz;    private final Map<String, String> headers;    private final Response.Listener<T> listener;    public GsonRequest(String url, Class<T> clazz, Map<String, String> headers,                       Listener<T> listener, ErrorListener errorListener) {        super(Method.GET, url, errorListener);        this.clazz = clazz;        this.headers = headers;        this.listener = listener;    }    @Override    public Map<String, String> getHeaders() throws AuthFailureError {        return headers != null ? headers : super.getHeaders();    }    @Override    protected Response<T> parseNetworkResponse(NetworkResponse response) {        try {            String json = new String(                    response.data,                    HttpHeaderParser.parseCharset(response.headers));            return Response.success(                    gson.fromJson(json, clazz),                    HttpHeaderParser.parseCacheHeaders(response));        } catch (UnsupportedEncodingException e) {            return Response.error(new ParseError(e));        } catch (JsonSyntaxException e) {            return Response.error(new ParseError(e));        }    }    @Override    protected void deliverResponse(T response) {        listener.onResponse(response);    }}

在实际调用的时候,和普通的请求类似:

    private void personRequest() {        GsonRequest<Person> gsonRequest = new GsonRequest<Person>(                TEST_URL,                Person.class,                null,                new Response.Listener<Person>() {                    @Override                    public void onResponse(Person response) {                        txtDisplay.setText("size: " + response.getContacts().size());                    }                },                new Response.ErrorListener() {                    @Override                    public void onErrorResponse(VolleyError error) {                        Log.e(TAG, "onErrorResponse, error: " + error.getMessage());                    }                }        );        VolleyController.getInstance(this).addToRequestQueue(gsonRequest, TAG);    }

实体类Person类:(在AS下可以使用gson插件来生成)

package com.example.volleylearn.model;import java.util.List;/** * Created by youngbear on 16/10/18. */public class Person {    /**     * id : c200     * name : Ravi Tamada     * email : ravi@gmail.com     * address : xx-xx-xxxx,x - street, x - country     * gender : male     * phone : {"mobile":"+91 0000000000","home":"00 000000","office":"00 000000"}     */    private List<ContactsBean> contacts;    public List<ContactsBean> getContacts() {        return contacts;    }    public void setContacts(List<ContactsBean> contacts) {        this.contacts = contacts;    }    public static class ContactsBean {        private String id;        private String name;        private String email;        private String address;        private String gender;        /**         * mobile : +91 0000000000         * home : 00 000000         * office : 00 000000         */        private PhoneBean phone;        public String getId() {            return id;        }        public void setId(String id) {            this.id = id;        }        public String getName() {            return name;        }        public void setName(String name) {            this.name = name;        }        public String getEmail() {            return email;        }        public void setEmail(String email) {            this.email = email;        }        public String getAddress() {            return address;        }        public void setAddress(String address) {            this.address = address;        }        public String getGender() {            return gender;        }        public void setGender(String gender) {            this.gender = gender;        }        public PhoneBean getPhone() {            return phone;        }        public void setPhone(PhoneBean phone) {            this.phone = phone;        }        public static class PhoneBean {            private String mobile;            private String home;            private String office;            public String getMobile() {                return mobile;            }            public void setMobile(String mobile) {                this.mobile = mobile;            }            public String getHome() {                return home;            }            public void setHome(String home) {                this.home = home;            }            public String getOffice() {                return office;            }            public void setOffice(String office) {                this.office = office;            }        }    }}

测试代码位置:https://github.com/YoungBear/VolleyLearn

参考:

http://www.androidhive.info/2014/05/android-working-with-volley-library-1/

http://bxbxbai.github.io/2014/09/14/android-working-with-volley/

https://developer.android.com/training/volley/index.html

http://blog.csdn.net/guolin_blog/article/details/17482165

http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/1018/1800.html

0 0
原创粉丝点击