1.什么是Volley?
Volley是一个网络通信库,它是对网络操作的一个封装框架,能够简化网络的相关操作,同时使网络更快、更简单、更健壮。
2.Volley有什么用?
上面这张图是在2013年Google I/O 大会中,引入Volley时所采用的图,由于Volley是一个网络通信库,那么这张图可以很清晰的告诉我们Volley使用的场景,即是适用于数据量不大但是网络通信很频繁的时候,如JSON/XML文本数据或图片加载等操作,不适用与大量数据的网络操作,如大数据的下载,文件上传和流媒体。
复习:Android中网络通信常用类:HttpURLConnection、HttpClient、AsyncTask、AsyncTaskLoader、Thread+handler等。
3.Volley原理
Volley使用线程池作为基本结构:线程分为main thread,cache thread,network thread.
结构图:
4.Volley的使用
任意创建一个规范的Android项目,然后在src目录下新建一个包com.android.volly,将Volleyball源码拷到这个包下就可以了。
核心代码:
可以将所有的操作封装成一个工具类,这里RequestQueue类和ImageLoader类在内存中始终只存在一个对象:
1 package com.qf.utils;
2
3 import java.io.IOException;
4 import java.lang.ref.SoftReference;
5 import java.util.HashMap;
6 import java.util.Map;
7
8 import android.content.Context;
9 import android.graphics.Bitmap;
10 import android.support.v4.util.LruCache;
11
12 import com.android.volley.RequestQueue;
13 import com.android.volley.toolbox.ImageLoader;
14 import com.android.volley.toolbox.Volley;
15
16 public class VolleyUtils {
17
18 public static RequestQueue mQueue;
19 public static ImageLoader mLoader;
20
21 private static LruCache<String,Bitmap> lruCache;//强引用缓存,一级缓存,特点:使用最近最少使用的算法,将旧数据移除,为新数据提供空间
22 private static Map<String,SoftReference<Bitmap>> softCache; //软引用缓存,二级缓存
23
24
25 public static RequestQueue getQueue(Context context){
26 if(mQueue==null){
27 mQueue=Volley.newRequestQueue(context);
28 }
29
30 return mQueue;
31 }
32
33 public static ImageLoader getLoader(Context context){
34 if(mLoader==null){
35 //实例化二级缓存
36 softCache=new HashMap<String, SoftReference<Bitmap>>();
37
38 //实例化一级缓存
39 lruCache=new LruCache<String, Bitmap>(2*1024*1024){ //缓存的内存空间为2M
40 @Override
41 protected int sizeOf(String key, Bitmap value) {
42 // TODO 计算存放成员的大小,返回字节大小
43 return value.getRowBytes()*value.getHeight();
44 }
45
46 @Override
47 protected void entryRemoved(boolean evicted, String key,
48 Bitmap oldValue, Bitmap newValue) {
49 // TODO 移除旧成员
50
51 if(evicted)
52 //将移除的成员存放到二级缓存中
53 softCache.put(key, new SoftReference<Bitmap>(oldValue));
54
55 super.entryRemoved(evicted, key, oldValue, newValue);
56 }
57 };
58
59 mLoader=new ImageLoader(getQueue(context), new ImageLoader.ImageCache() {
60
61 @Override
62 public void putBitmap(String url, Bitmap bitmap) {
63 // TODO 将图片存放在缓存中的方法
64 //将图片存放在一级缓存中
65 lruCache.put(url, bitmap);
66
67 //将图片也存放在扩展卡
68 try {
69 ImageUtils.saveImg(url, bitmap);
70 } catch (IOException e) {
71 e.printStackTrace();
72 }
73 }
74
75 @Override
76 public Bitmap getBitmap(String url) {
77 // TODO 从缓存中读取图片的方法
78 //先从一级缓存中获取
79 Bitmap b=lruCache.get(url);
80 if(b==null){
81 //从二级缓存中读取
82 SoftReference<Bitmap> reference=softCache.get(url);
83 if(reference!=null){ //二级缓存中存在
84 b=reference.get();
85 if(b!=null){
86 //将图片对象存放在一级缓存
87 lruCache.put(url, b);
88
89 //从二级缓存中移除
90 softCache.remove(reference);
91 }
92 }else{ //从三级缓存中读取--扩展卡
93 b=ImageUtils.getImg(url);
94 if(b!=null){
95 //将图片存放到一级缓存中
96 lruCache.put(url, b);
97 }
98 }
99 }
100 return b;
101 }
102 });
103 }
104
105 return mLoader;
106 }
107
108 }
Volley 工具类
使用Volley获取网络图片的三种方法:
1. ImageRequest类
1 // 参数2: 图片下载成功, 自动回调这个接口
2 // 参数3: 内存中Bitmap 最大的宽度限制,用于降低内存的消耗
3 // 参数4:内存中 Bitmap 最大的高度限制,用于降低内存的消耗
4 // 参数5:告诉 BitmapFactory,在生成Bitmap的时候,一个像素,包含的信息
5 // 参数 6:图片加载失败的时候,回调
6 ImageRequest request = new ImageRequest(url,
7 new Response.Listener<Bitmap>() {
8 @Override
9 public void onResponse(Bitmap response) {
10 imageView.setImageBitmap(response);
11 }
12 }
13 ,200,100,Bitmap.Config.ARGB_8888,
14 new Response.ErrorListener() {
15 @Override
16 public void onErrorResponse(VolleyError error) {
17 imageView.setImageResource(R.drawable.ic_launcher);
18 }
19 });
ImageRequest类的使用
2.ImageLoader类
1 // 参数1 : 用于实际的网络请求
2 // 参数2 : ImageCache 内存缓存
3 imageLoader = new ImageLoader(requestQueue, new ImageLoader.ImageCache() {
4 LruCache<String,Bitmap> cache = new LruCache<>(10);
5 @Override
6 public Bitmap getBitmap(String url) {
7 return cache.get(url);
8 }
9
10 @Override
11 public void putBitmap(String url, Bitmap bitmap) {
12 cache.put(url,bitmap);
13 }
14 });
ImageLoader类的初始化
1 //方法1
2 /*imageLoader.get(url, new ImageLoader.ImageListener() {
3 @Override
4 public void onResponse(ImageLoader.ImageContainer response, boolean isImmediate) {
5 // TODO 设置图片
6 }
7
8 @Override
9 public void onErrorResponse(VolleyError error) {
10 // TODO 设置失败图片
11 }
12 });*/
13
14 //方法2
15 ImageView imageView = (ImageView) findViewById(R.id.imageView);
16 imageLoader.get(url+"sdf",
17 ImageLoader.getImageListener(imageView,R.drawable.ic_launcher,android.R.drawable.ic_delete));
ImageLoader类的使用
3.NetworkImageView类
NetworkImageVIew类时Volley自定义的一个类,它继承ImageView,在XML文件中可以像ImageView控件一样使用,与ImageView的使用没有区别,只是NetworkImageView是用来加载网络图片的ImageView。
1 <?xml version="1.0" encoding="utf-8"?>
2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 android:orientation="vertical"
4 android:layout_width="fill_parent"
5 android:layout_height="fill_parent"
6 >
7
8 <ImageView
9 android:id="@+id/imageView"
10 android:layout_width="wrap_content"
11 android:layout_height="wrap_content"
12 />
13 <com.android.volley.toolbox.NetworkImageView
14 android:id="@+id/networkImageView"
15 android:layout_width="wrap_content"
16 android:layout_height="wrap_content"
17 />
18 <android.support.v4.view.ViewPager
19 android:id="@+id/viewPager"
20 android:layout_width="match_parent"
21 android:layout_height="match_parent"/>
22
23 </LinearLayout>
NetworkImageView在XML文件中使用
1 //NetworkImageView
2 NetworkImageView networkImageView = (NetworkImageView) findViewById(R.id.networkImageView);
3 networkImageView.setImageUrl(url,imageLoader);
NetworkImageView的使用