volley学习

2015/6/12 posted in  Android

背景

Vollry特别适合数据量不大但是通信频繁的场景。

比如以前从网上下载图片的步骤可能这样的流程:

  • 在ListAdatpter-getview()方法里开始图像的读取
  • 通过AsyncTask等机制使用HttpURLConnection从服务器去读取图片资源
  • 在AsyncTask-onPostExecute()里设置相应的Imageview的属性

而在Volley下,只需要一个函数即可

Volley提供的功能:

  • JSON,图像等异步下载;
  • 网络请求的排序
  • 网络请求的优先级处理
  • 缓存
  • 多级别取消请求
  • 和Activity的生命周期的联动(Activity结束的同时,取消所有网络请求)

下载volley jar包

法1

$ git clone https://android.googlesource.com/platform/frameworks/volley
$ cd volley
$ android update project -p .
$ ant jar

复制bin/volley.jar 到工程 libs/目录
在android studio中 add as library

法2

直接下载 http://api.androidhive.info/volley/volley.jar

法3

gradle加入

dependencies {
    compile 'com.mcxiaoke.volley:library:1.0.+'
}

非官方的镜像

StringRequest的用法

加上网络权限

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

获取RequestQueue对象

RequestQueue mQueue = Volley.newRequestQueue(context);  

注意这里拿到的RequestQueue是一个请求队列对象,它可以缓存所有的HTTP请求,然后按照一定的算法并发地发出这些请求。RequestQueue内部的设计就是非常合适高并发的,因此我们不必为每一次HTTP请求都创建一个RequestQueue对象,这是非常浪费资源的,基本上在每一个需要和网络交互的Activity中创建一个RequestQueue对象就足够了。

创建一个StringRequest对象

StringRequest stringRequest = new StringRequest("http://www.baidu.com",
        new Response.Listener<String>() {
            @Override
            public void onResponse(String response) {
                Log.d("TAG", response);
            }
        }, new Response.ErrorListener() {
    @Override
    public void onErrorResponse(VolleyError error) {
        Log.e("TAG", error.getMessage(), error);
    }
});

参数1:目标服务器地址
参数2:响应成功的回调函数
参数3:响应十八的回调函数

将这个StringRequest对象添加到RequestQueue

mQueue.add(stringRequest); 

post请求

Volley会尝试调用StringRequest的父类——Request中的getParams()方法来获取POST参数,,我们只需要在StringRequest的匿名类中重写getParams()方法,在这里设置POST参数就可以了

StringRequest stringRequest = new StringRequest(Method.POST, url,  listener, errorListener) {  
    @Override  
    protected Map<String, String> getParams() throws AuthFailureError {  
        Map<String, String> map = new HashMap<String, String>();  
        map.put("params1", "value1");  
        map.put("params2", "value2");  
        return map;  
    }  
}; 

JsonRequest的用法

JsonRequest有两个直接的子类
JsonObjectRequest和JsonArrayRequest,从名字上你应该能就看出它们的区别了吧?一个是用于请求一段JSON数据的,一个是用于请求一段JSON数组的

同理

JsonObjectRequest jsonObjectRequest = new JsonObjectRequest("http://m.weather.com.cn/data/101010100.html", null,  
        new Response.Listener<JSONObject>() {  
            @Override  
            public void onResponse(JSONObject response) {  
                Log.d("TAG", response.toString());  
            }  
        }, new Response.ErrorListener() {  
            @Override  
            public void onErrorResponse(VolleyError error) {  
                Log.e("TAG", error.getMessage(), error);  
            }  
        }); 
        ```


```java
mQueue.add(jsonObjectRequest);  

使用Volley加载网络图片

ImageRequest的用法

创建RequestQueue对象

RequestQueue mQueue = Volley.newRequestQueue(context);  

实例化ImageRequest对象


public void getImg(View view) {
    RequestQueue mQueue = Volley.newRequestQueue(this);
    ImageRequest imageRequest = new ImageRequest(
            "http://avatar.csdn.net/blogpic/20140903135550859.jpg",
            new Response.Listener<Bitmap>() {
                @Override
                public void onResponse(Bitmap response) {
                    imageView.setImageBitmap(response);
                }
            }, 0, 0, Bitmap.Config.RGB_565, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            imageView.setImageResource(R.mipmap.ic_launcher);
        }
    });

参数1:图片地址
参数2:回调函数,在此把接受的bitmap设置到imageView中
参数3:图片最大宽度
参数4:图片最大高度
参数5:图片的颜色(ARGB_8888最好的颜色。RGB_565每个像素2字节)

imageRequest加入队列

mQueue.add(imageRequest); 

ImageLoader的用法

  1. 创建一个RequestQueue对象。
  2. 创建一个ImageLoader对象。
  3. 获取一个ImageListener对象。
  4. 调用ImageLoader的get()方法加载网络上的图片。
    #### 新建一个ImageLoader对
ImageLoader imageLoader = new ImageLoader(mQueue, new ImageCache() {  
    @Override  
    public void putBitmap(String url, Bitmap bitmap) {  
    }  
  
    @Override  
    public Bitmap getBitmap(String url) {  
        return null;  
    }  
});  

参数1:RequestQueue
参数2:ImageCache对象

获取一个ImageListener对象

ImageListener listener = ImageLoader.getImageListener(imageView,  
        R.drawable.default_image, R.drawable.failed_image);

我们通过调用ImageLoader的getImageListener()方法能够获取到一个ImageListener对象,getImageListener()方法接收三个参数,第一个参数指定用于显示图片的ImageView控件,第二个参数指定加载图片的过程中显示的图片,第三个参数指定加载图片失败的情况下显示的图片。

调用ImageLoader的get()方法来加载图片

imageLoader.get("http://img.my.csdn.net/uploads/201404/13/1397393290_5765.jpeg", listener);  

cache的实现

BitmapCache并实现了ImageCache接口

public class BitmapCache implements ImageCache {  
  
    private LruCache<String, Bitmap> mCache;  
  
    public BitmapCache() {  
        int maxSize = 10 * 1024 * 1024;  
        mCache = new LruCache<String, Bitmap>(maxSize) {  
            @Override  
            protected int sizeOf(String key, Bitmap bitmap) {  
                return bitmap.getRowBytes() * bitmap.getHeight();  
            }  
        };  
    }  
  
    @Override  
    public Bitmap getBitmap(String url) {  
        return mCache.get(url);  
    }  
  
    @Override  
    public void putBitmap(String url, Bitmap bitmap) {  
        mCache.put(url, bitmap);  
    }  
  
}  

可以看到,这里我们将缓存图片的大小设置为10M。接着修改创建ImageLoader实例的代码,第二个参数传入BitmapCache的实例,如下所示:

ImageLoader imageLoader = new ImageLoader(mQueue, new BitmapCache());  

除了以上两种方式之外,Volley还提供了第三种方式来加载网络图片,即使用NetworkImageView。不同于以上两种方式,NetworkImageView是一个自定义控制,它是继承自ImageView的,具备ImageView控件的所有功能,并且在原生的基础之上加入了加载网络图片的功能。NetworkImageView控件的用法要比前两种方式更加简单,大致可以分为以下五步:

  1. 创建一个RequestQueue对象。
  2. 创建一个ImageLoader对象。
  3. 在布局文件中添加一个NetworkImageView控件。
  4. 在代码中获取该控件的实例。
  5. 设置要加载的图片地址。

其中,第一第二步和ImageLoader的用法是完全一样的,因此这里我们就从第三步开始学习了。首先修改布局文件中的代码,在里面加入NetworkImageView控件,如下所示:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:layout_width="fill_parent"  
    android:layout_height="fill_parent"  
    android:orientation="vertical" >  
  
    <Button  
        android:id="@+id/button"  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:text="Send Request" />  
      
    <com.android.volley.toolbox.NetworkImageView   
        android:id="@+id/network_image_view"  
        android:layout_width="200dp"  
        android:layout_height="200dp"  
        android:layout_gravity="center_horizontal"  
        />  
  
</LinearLayout>  

获取控件

networkImageView = (NetworkImageView) findViewById(R.id.network_image_view);  

得到了NetworkImageView控件的实例之后,我们可以调用它的setDefaultImageResId()方法、setErrorImageResId()方法和setImageUrl()方法来分别设置加载中显示的图片,加载失败时显示的图片,以及目标图片的URL地址,如下所示:

networkImageView.setDefaultImageResId(R.drawable.default_image);  
networkImageView.setErrorImageResId(R.drawable.failed_image);  
networkImageView.setImageUrl("http://img.my.csdn.net/uploads/201404/13/1397393290_5765.jpeg",  
                imageLoader);  

NetworkImageView并不需要提供任何设置最大宽高的方法也能够对加载的图片进行压缩。这是由于NetworkImageView是一个控件,在加载图片的时候它会自动获取自身的宽高,然后对比网络图片的宽度,再决定是否需要对图片进行压缩。也就是说,压缩过程是在内部完全自动化的,并不需要我们关心,NetworkImageView会始终呈现给我们一张大小刚刚好的网络图片,不会多占用任何一点内存,这也是NetworkImageView最简单好用的一点吧。

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