Android网络请求框架 Volley

Volley是2013年谷歌官方推出的Android平台的网络通信库,Volley适用于并发和对效率、性能要求比较高的场景。

1.Volley的特点

优点:
(1)使通信更快、更简单
(2)高效的get、post网络请求以及网络图像的高效率异步处理请求
(3)能对网络请求进行排序、优先级处理
(4)网络图片加载和缓存
(5)多级别取消请求,当有多个网络请求同时进行的时候,可以进行同时取消操作
(6)和Activity生命周期的联动,当Activity结束销毁时,可以同时取消网络请求操作
(7)性能稳定

缺点:
(1)不适合数据的上传下载

2.Volley的下载

Github下载:
https://github.com/mcxiaoke/android-volley

Maven下载:
http://central.maven.org/maven2/com/mcxiaoke/volley/library/

3.Volley的get、post请求方式的使用

在进行get、post请求之前要确定请求的数据返回的类型是哪种类型,Volley提供了三种类型:
StringRequest:返回结果类型不确定的情况使用
JsonObjectRequest:返回结果类型为JsonObject
JsonArrayRequest:返回结果类型为JsonArray

(1)首先需要为应用程序建立全局请求队列

public class MyApplication extends Application {
    public static RequestQueue queue;
    @Override
    public void onCreate() {
        super.onCreate();
        // 建立Volley全局请求队列
        queue = Volley.newRequestQueue(getApplicationContext()); // 实例化RequestQueue对象 
    }
    public static RequestQueue getHttpQueue() {
        return queue;
    }
}

注意:需要把MyApplication注册到AndroidManifest.xml中,并加上网络请求权限。

(2)Volley的get请求

/** * 返回结果类型不确定的情况下 */
private void volleyGet(String url) {
    /** * int method 请求方式 * String url 请求接口地址 * Listener<String> listener 请求成功的回调 * ErrorListener errorListener 请求失败的回调 */
    StringRequest request = new StringRequest(Method.GET, url, new Response.Listener<String>() {
        @Override
        public void onResponse(String arg0) {
            System.out.println("请求成功:" + arg0); // 输出请求成功的返回结果
        }
    }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError arg0) {
            System.out.println("请求失败:" + arg0);
        }
    });
    request.setTag("homeGet"); // 这个Tag设置的要有意义
    MyApplication.getHttpQueue().add(request); // 将请求加入到全局变量
}

/** * 返回结果类型为JsonObject * 注意:返回结果类型为JsonArray的请求方法和JsonObject类似 */
private void volleyJOGet(String url) {
    /** * int method 请求方式 * String url 请求接口地址 * JSONObject jsonRequest Get为null,Post传递负载请求参数的Object * Listener<JSONObject> listener 请求成功的回调 * ErrorListener errorListener 请求失败的回调 */
    JsonObjectRequest request = new JsonObjectRequest(Method.GET, url, null, new Response.Listener<JSONObject>() {
        @Override
        public void onResponse(JSONObject arg0) {
            System.out.println("请求成功:" + arg0.toString()); // 输出请求成功返回的JSONObject,这里可以直接进行json解析了
        }
    }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError arg0) {
            System.out.println("请求失败:" + arg0);
        }
    });
    request.setTag("homeJoGet"); // 这个Tag设置的要有意义
    MyApplication.getHttpQueue().add(request); // 将请求加入到全局变量
}

(3)Volley的post请求
首先我们用HashMap封装post请求的参数:

Map<String, String> hashmap = new HashMap<String, String>();
hashmap.put("zhangsan", "12"); // 将传递的参数添加进来
hashmap.put("key", "12"); 

然后就可以用封装好的参数向URL提交post请求了:

/** * 返回结果类型不确定的情况下 */
private void volleyPost(String url, final HashMap<String, String> hashmap) {
    /** * int method 请求方式 * String url 请求接口地址,使用post则请求参数不能写在URL里,而是使用参数化的传递 * 例如url:http://www.demo.com/login/get? * 完整为:url:http://www.demo.com/login/get?zhangsan=12&key=12 * Listener<String> listener 请求成功的回调 * ErrorListener errorListener 请求失败的回调 */
    StringRequest request = new StringRequest(Method.POST, url, new Response.Listener<String>() {
        @Override
        public void onResponse(String arg0) {
            System.out.println("请求成功:" + arg0); // 输出请求成功的返回结果
        }
    }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError arg0) {
            System.out.println("请求失败:" + arg0);
        }
    }){
        // getParams()方法表示用户在volley中使用post方式请求数据中参数的传递
        // volley会自动调用getParams()中传递过来的请求参数
        @Override
        protected Map<String, String> getParams() {
            return hashmap;
        }
    };
    request.setTag("homePost"); // 这个Tag设置的要有意义
    MyApplication.getHttpQueue().add(request); // 将请求加入到全局变量
}

/** * 返回结果类型为JsonObject * 注意:返回结果类型为JsonArray的请求方法和JsonObject类似 */
private void volleyJOPost(String url, final HashMap<String, String> hashmap) {
    JSONObject object = new JSONObject(hashmap);
    /** * int method 请求方式 * String url 请求接口地址,使用post则请求参数不能写在URL里,而是使用参数化的传递 * 例如url:http://www.demo.com/login/get? * 完整为:url:http://www.demo.com/login/get?zhangsan=12&key=12 * JSONObject jsonRequest 传递负载请求参数的Object * Listener<JSONObject> listener 请求成功的回调 * ErrorListener errorListener 请求失败的回调 */
    JsonObjectRequest request = new JsonObjectRequest(Method.POST, url, object, new Response.Listener<JSONObject>() {
        @Override
        public void onResponse(JSONObject arg0) {
            System.out.println("请求成功:" + arg0.toString()); // 输出请求成功返回的JSONObject,这里可以直接进行json解析了
        }
    }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError arg0) {
            System.out.println("请求失败:" + arg0);
        }
    });
    request.setTag("homeJoPost"); // 这个Tag设置的要有意义
    MyApplication.getHttpQueue().add(request); // 将请求加入到全局变量
}

4.Volley的网络请求队列

在我们使用Volley时,要建立一个全局的请求队列,然后我们在建立一个请求,把请求加入到全局队列中,这样app的请求是通过队列管理的,方便我们进行取消某个请求或者取消全部请求。

5.Volley与Activity生命周期的联动

Volley的生命周期和Activity的生命周期是关联在一起的,可以在Activity销毁时,同时关闭请求。
一般我们将Volley和Activity的生命周期关联的时候,都需要设置我们的Tag标签(通过Tag标签在全局队列中查找),然后在onStop()方法中执行取消请求。

@Override
protected void onStop() {
    super.onStop();
    MyApplication.getHttpQueue().cancelAll("homeGet"); // 通过给定的tag值,将指定的队列全部关闭
}

6.Volley的二次回调封装-自定义Get

全局使用一个方式,可控,可自定义定制需求

首先我们创建自己的请求管理VolleyRequest,其中listener, errorListener还没有创建

public class VolleyRequest {
    public static StringRequest request;
    public static Context context;
    /** * GET请求 * @param context * @param url * @param tag */
    public static void RequestGet(Context context, String url, String tag){
        MyApplication.getHttpQueue().cancelAll(tag); // 将tag标签的请求都取消掉,放在重复请求
        StringRequest request = new StringRequest(Method.GET, url, listener, errorListener);

        request.setTag(tag); 
        MyApplication.getHttpQueue().add(request); 
        MyApplication.getHttpQueue().start();
    }
}

接下来创建自定义VolleyInterface抽象类

public abstract class VolleyInterface {
    public Context context;
    public static Response.Listener<String> listener;
    public static Response.ErrorListener errorListener;

    public VolleyInterface(Context context, Response.Listener<String> listener, 
            Response.ErrorListener errorListener){
        this.context = context;
        this.listener = listener;
        this.errorListener = errorListener;
    }
    public abstract void onMySuccess(String result);
    public abstract void onMyError(VolleyError error);
    /** * 请求成功 * @return */
    public Response.Listener<String> successListener(){
        listener = new Response.Listener<String>(){
            @Override
            public void onResponse(String arg0) {
                onMySuccess(arg0);
            }
        };
        return listener;
    }
    /** * 请求失败 * @return */
    public Response.ErrorListener errorListener(){
        errorListener = new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError arg0) {
                onMyError(arg0);
            }
        };
        return errorListener;
    }
}

接下来我们就可以在VolleyRequest中使用VolleyInterface了:

public class VolleyRequest {
    public static StringRequest request;
    public static Context context;
    /** * GET请求 * @param context * @param url * @param tag * @param vi */
    public static void RequestGet(Context context, String url, String tag, VolleyInterface vi){
        MyApplication.getHttpQueue().cancelAll(tag); // 将tag标签的请求都取消掉,放在重复请求
        StringRequest request = new StringRequest(Method.GET, url, vi.successListener(), vi.errorListener());

        request.setTag(tag); 
        MyApplication.getHttpQueue().add(request); 
        MyApplication.getHttpQueue().start();
    }
}

到此,自定义get就写好了。

7.Volley的二次回调封装-自定义Post

在VolleyRequest中添加自定义post方法:

public class VolleyRequest {
    public static StringRequest request;
    public static Context context;
    /** * GET请求 * @param context * @param url * @param tag * @param vi */
    public static void RequestGet(Context context, String url, String tag, VolleyInterface vi){
        MyApplication.getHttpQueue().cancelAll(tag); // 将tag标签的请求都取消掉,放在重复请求
        StringRequest request = new StringRequest(Method.GET, url, vi.successListener(), vi.errorListener());

        request.setTag(tag); 
        MyApplication.getHttpQueue().add(request); 
        MyApplication.getHttpQueue().start();
    }
    /** * POST请求 * @param context * @param url * @param tag * @param hashmap * @param vi */
    public static void RequestPost(Context context, String url, String tag, final HashMap<String, String> hashmap, VolleyInterface vi){
        MyApplication.getHttpQueue().cancelAll(tag); // 将tag标签的请求都取消掉,放在重复请求
        StringRequest request = new StringRequest(Method.GET, url, vi.successListener(), vi.errorListener()){
            @Override
            protected Map<String, String> getParams() {
                return hashmap;
            }
        };
        request.setTag(tag); 
        MyApplication.getHttpQueue().add(request); 
        MyApplication.getHttpQueue().start();
    }
}

8.在Activity中使用二次封装好的Volley框架

/** * 返回结果类型不确定的情况下 */
private void volleyGet(String url) {
    VolleyRequest.RequestGet(this, url, "homeGet", new VolleyInterface(this, 
            VolleyInterface.listener, VolleyInterface.errorListener) {
        @Override
        public void onMySuccess(String result) {
            System.out.println("请求成功:" + result);
        }
        @Override
        public void onMyError(VolleyError error) {
            System.out.println("请求失败:" + error.toString());
        }
    });
}

9.Volley使用ImageRequest获取网络图片

Volley加载网络图片可以使用ImageRequest或者ImageLoader,监听使用ImageListener,网络图片的显示也可以用NetworkImageView或者ImageView。

public class MainActivity extends Activity {
    private ImageView iv_img;
    String url = "";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        iv_img = (ImageView)findViewById(R.id.iv_img);
        /** * String url 图片地址 * Listener<Bitmap> listener 图片请求成功的回调 * int maxWidth 图片大小的压缩处理,设置0则显示原图 * int maxHeight * Config decodeConfig 加载图片的格式 * ErrorListener errorListener 请求失败的回调 */
        ImageRequest request = new ImageRequest(url, new Response.Listener<Bitmap>() {
            @Override
            public void onResponse(Bitmap arg0) {
                iv_img.setImageBitmap(arg0);
            }
        }, 200, 200, Config.RGB_565, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError arg0) {
                iv_img.setBackgroundResource(R.drawable.ic_launcher); // 显示请求失败的图片
            }
        });
    }
}

10.Volley使用ImageLoader缓存网络图片

(1)创建ImageLoader

public class MainActivity extends Activity {
    private ImageView iv_img;
    String url = "";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        iv_img = (ImageView)findViewById(R.id.iv_img);
        /** * RequestQueue queue 请求队列 * ImageCache imageCache 缓存 */
        ImageLoader loader = new ImageLoader(MyApplication.getHttpQueue(), new BitmapCache());
    }
}

这里需要使用到imageCache(创建了BitmapCache实例),ImageCache单独使用是起不到缓存作用的,所以还要结合LruCache,接下来自定义一个ImageCache缓存类:

public class BitmapCache implements ImageCache{

    public LruCache<String, Bitmap> cache;
    public int maxSize = 10*1024*1024; // 10M,定义LruCache最大缓存大小,当超过会启动自动回收
    public BitmapCache(){
        cache = new LruCache<String, Bitmap>(maxSize){
            @Override
            protected int sizeOf(String key, Bitmap value) {
                return value.getRowBytes() * value.getHeight();
            }
        };
    }
    @Override
    public Bitmap getBitmap(String arg0) {
        return cache.get(arg0);
    }
    @Override
    public void putBitmap(String arg0, Bitmap arg1) {
        cache.put(arg0, arg1);
    }
}

(2)下来需要创建ImageListener来监听图片的加载过程:

public class MainActivity extends Activity {
    private ImageView iv_img;
    String url = "";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        iv_img = (ImageView)findViewById(R.id.iv_img);
        /** * RequestQueue queue 请求队列 * ImageCache imageCache 缓存 */
        ImageLoader loader = new ImageLoader(MyApplication.getHttpQueue(), new BitmapCache());
        /** * ImageView view ImageView控件 * int defaultImageResId 默认的加载图片 * int errorImageResId 加载出错的时候显示的图片 */
        ImageListener listener = ImageLoader.getImageListener(iv_img, 
                R.drawable.ic_launcher, R.drawable.ic_launcher);
        loader.get(url, listener); // 获取网络图片
    }
}

到此使用ImageLoader缓存网络图片就已经完成了。

10.Volley使用NetworkImageView加载网络图片

NetworkImageView是要搭配ImageLoader进行使用的:

public class MainActivity extends Activity {
    private NetworkImageView niv_img;
    String url = "";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        niv_img = (NetworkImageView)findViewById(R.id.niv_img);
        /** * RequestQueue queue 请求队列 * ImageCache imageCache 缓存 */
        ImageLoader loader = new ImageLoader(MyApplication.getHttpQueue(), new BitmapCache());
        niv_img.setDefaultImageResId(R.drawable.ic_launcher); // 设置默认图片
        niv_img.setErrorImageResId(R.drawable.ic_launcher); // 设置默认图片
        niv_img.setImageUrl(url, loader); // 设置默认图片
    }
}

你可能感兴趣的:(android,框架,网络,android平台)