手记

Volley的使用以及源码分析(一)

一、Volley的使用

1.1 Volley简介

Volley是Google I/O 2013发布的一款基于Android平台的网络框架,它的优点有:
1) 默认Android2.3及以上基于 HttpURLConnection,2.3以下基于HttpClient;
2) 提供了两种缓存机制:磁盘缓存和内存缓存,符合Http缓存语义的缓存机制;
3) 支持指定请求的优先级;
4) 提供多样的取消机制:特定任务取消以及多任务取消;
5) 提供简便的图片加载工具(ImageRequest、ImageLoader);
6) 一个优秀的框架.

不足之处:它只适应数据量小,通信频繁的网络操作,如果数据量大如音频、视频等传输,就不要使用Volley为好.下图是官方给出的Velloy网络框架示意图,就表明该框架适合数据量不大但很频繁的场景.
 

1.2 获取Volley

1) 可以直接从google上git clone下来:
git clone https://android.googlesource.com/platform/frameworks/volley
然后使用命令:android update project -p . ant jar生成一个Volley.jar包,直接添加到工程中就可以使用了.

2) 或者从github上下载源码
https://github.com/Fox-Legend/android-volley

1.3 使用Volley

Volley中构建了很多工具网络请求工具类,如StringRequest、JsonArrayRequest、JsonObjectRequest、ImageRequest等,这些都是常用的网络请求.
Volley提供了一个请求队列RequestQueue专门用于存放用户的网络请求,所有的request申请后都添加到这个队列中缓存,然后按照一定的算法并发地发出这些请求,
一般网络请求队列在整个APP内使用是一个全局对象,所以最好写到Application中,

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

public class AppApplication extends Application {

  /**

   * 建立请求队列

   */

  private static RequestQueue mQueue;

  @Override

  public void onCreate() {

      super.onCreate();

      this.mQueue = Volley.newRequestQueue(getApplicationContext());

  }

  public static RequestQueue   getRequestQueue(){

      return mQueue;

  }

}

在创建RequestQueue队列对象的构造函数中,已经调用了RequestQueue的start方法.
对应的需要修改AndroidManifest.xml文件,是的App对应的Application对象为AppApplication.
不要忘记添加访问网络的权限:

1

2

3

4

5

6

7

8

<application

        android:name=".AppApplication"

        android:allowBackup="true"

        android:icon="@mipmap/ic_launcher"

        android:label="@string/app_name"

        android:supportsRtl="true"

        android:theme="@style/AppTheme">

        <activity android:name=".MainActivity">

(1) 建立一个JsonArrayRequest发送Http请求,并添加到RequestQueue中,返回Json数据:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

private static final String TAG = "MainActivity";

    private final String mUrl = "http://10.8.204.173:5000/shouye/newdata/1";

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

          setContentView(R.layout.activity_main);

        VolleyGet();

    }

    /**

     * 网络请求方式为Get,返回Json

     */

    private void VolleyGet() {

        /**

         * 建立JsonArrayRequest请求

         */

        JsonArrayRequest request = new   JsonArrayRequest(Request.Method.GET,mUrl,null, new Response.Listener<JSONArray>() {

            @Override

            public void onResponse(JSONArray response) {

                Toast.makeText(MainActivity.this,"the response:" +   response.toString(),Toast.LENGTH_SHORT).show();

            }

        }, new Response.ErrorListener() {

            @Override

            public void onErrorResponse(VolleyError error) {

                Log.e(TAG,error.toString());

            }

        });

        /**

         * 为request设置请求标签

         */

        request.setTag("JSONArrayRequest_GET");

        AppApplication.getRequestQueue().add(request);

    }

返回Json数据:
the response:
[{“star”:”53”,”date”:”06-18”,”title”:”美发图片长发卷发”,”urls”:[“http:\/\/t1.du114.com\/uploads\/tu\/201606\/changfa250\/2008111233241866_2.jpg”]}]
大家都知道Http的请求类型通常有两种,GET和POST,上面只是使用GET方式,若想要发送POST请求,只需要修改method==Request.Method.POST即可,再加添post请求内容params.
JsonArrayRequest其对应的构造函数参数列表为:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

/* 默认的请求方法是GET

 */

public JsonArrayRequest(String url, Listener<JSONArray>   listener, ErrorListener errorListener) {

     ...// 省略代码

}

/**

 * Creates a new request.

 * @param method the HTTP method to use:网络请求的方法,如GET和POST等

 * @param url URL to fetch the JSON from:网络请求的地址

 * @param jsonRequest A {@link JSONArray} to   post with the request. Null is allowed and

 *     indicates no parameters will be posted along with request

 * @param listener Listener to receive the   JSON response:请求返回结果监听

 * @param errorListener Error listener, or   null to ignore errors.:请求失败监听

 */

public JsonArrayRequest(int method, String url, JSONArray   jsonRequest,

                          Listener<JSONArray> listener, ErrorListener errorListener) {

    ...// 省略代码

}

总结上述过程总共就三步:
a、创建一个RequestQueue对象;
b、创建一个JsonArrayRequest对象;
c、将JsonArrayRequest对象添加到RequestQueue中.

在Volley中还提供了其它的Request,比如StringRequest/JsonObjectRequest等,而且还可以自定义Request.使用方法基本和上述一样.

(2) 除了一些基本字符数据的网络请求,Volley还可以加载图片数据,有两种请求方式:ImageLoader和ImageRequest
ImageRequest
ImageRequest和之前的request用法差不多,都是在创建对象后添加到RequestQueue中.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

/**

 * 利用ImageRequest加载图片

 */

private void VolleyImageRequest(final ImageView imageView) {

    int maxHeight = 480;

    int maxWidth = 640;

    String mPicUrl = "http://t1.du114.com/uploads/tu/201510/fengjing/rgj5thjkwlf.jpg";

    ImageRequest imgRequest = new ImageRequest(mPicUrl, new Response.Listener<Bitmap>() {

        @Override

        public void onResponse(Bitmap response) {

            imageView.setImageBitmap(response);

        }

    }, maxWidth,   maxHeight,ImageView.ScaleType.CENTER, Bitmap.Config.RGB_565,

            new Response.ErrorListener() {

        @Override

        public void onErrorResponse(VolleyError error) {

            Log.e(TAG,error.toString());

        }

    });

    imgRequest.setTag("ImageRequest_TAG");

      AppApplication.getRequestQueue().add(imgRequest);

}

可以看到,ImageRequest的构造函数能接收七个参数(原有的六个参数的方法最后也是调用该方法),第一个参数就是图片的URL地址。第二个参数是图片请求成功的回调, 这里我们可以把返回的Bitmap参数设置到ImageView中,第三第四个参数分别用于指定允许图片最大的宽度和高度,如果指定的网络图片的宽度或高度大于这里的最大值,则会对图片进行压缩,指定成0的话就表示不管图片有多大,都不会进行压缩. 第五个参数用于指定图片填充空间的缩放方式ScaleType,第六个参数用于指定图片的颜色属性,Bitmap.Config下的几个常量都可以在这里使用,其中ARGB_8888可以展示最好的颜色属性,每个图片像素占据4个字节的大小,而 RGB_565则表示每个图片像素占据2个字节大小。第七个参数是图片请求失败的回调,这里我们可以在请求失败时在ImageView中显示一张默认图片。
ImageLoader
ImageLoader也可以用于加载网络图片,并且内部也是使用ImageRequest来实现的,不过ImageLoader比ImageRequest要高效,因为它不仅可以对图片进行缓存而且还可以过滤重复的链接,避免重复发送请求.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

/**

 * 利用ImageLoader加载图片

 * @param mImgView

 */

private void VolletImageLoader(final ImageView mImgView) {

    int maxHeight = 480;

    int maxWidth = 640;

    String mPicUrl = "http://t1.du114.com/uploads/tu/201510/fengjing/rgj5thjkwlf.jpg";

    ImageLoader imgLoader = new   ImageLoader(AppApplication.getRequestQueue(),new BitmapCache());

    ImageLoader.ImageListener listener =

              ImageLoader.getImageListener(mImgView,android.R.drawable.ic_menu_rotate,android.R.drawable.ic_delete);

    imgLoader.get(mPicUrl,listener,maxWidth,maxHeight);

}

/**

  * BitmapCache

  */

public class BitmapCache implements ImageLoader.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 value) {

              return value.getRowBytes() * value.getHeight();

          }

      };

  }

  @Override

  public Bitmap getBitmap(String url) {

      return mCache.get(url);

  }

  @Override

  public void putBitmap(String url, Bitmap bitmap) {

      mCache.put(url,bitmap);

  }

}

可以看到,ImageLoader的构造函数接收两个参数,第一个参数就是RequestQueue对象,第二个参数是一个ImageCache对象,我们通过调用ImageLoader的getImageListener()方法能够获取到一个ImageListener对象,getImageListener()方法接收三个参数,第一个参数指定用于显示图片的ImageView控件,第二个参数指定加载图片的过程中显示的图片,第三个参数指定加载图片失败的情况下显示的图片。最后,调用ImageLoader的get()方法来加载图片。

Volley还特别为加载网络图片提供了NetworkImageView控件(其继承至ImageView),它将上述单独为ImageView设置加载时图片和加载失败的图片等功能封装在一起,更方便.

1

2

3

4

5

6

7

private void VolleyImageLoader(NetworkImageView mNetworkView) {

       String mPicUrl = "http://t1.du114.com/uploads/tu/201510/fengjing/rgj5thjkwlf.jpg";

       ImageLoader imgLoader = new   ImageLoader(AppApplication.getRequestQueue(),new BitmapCache());

       this.mNetworkView.setDefaultImageResId(android.R.drawable.ic_menu_rotate);

       this.mNetworkView.setErrorImageResId(android.R.drawable.ic_delete);

       this.mNetworkView.setImageUrl(mPicUrl,imgLoader);

   }

1.4 自定义Request

Volley允许用户按照自己的意愿定义特定的Request,那么怎么样去定义了? 在Volley中的所有Request都是继承至抽象类Request:
如StringRequest:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

/**

 * A canned request for retrieving the   response body at a given URL as a String.

 */

public class StringRequest extends Request<String> {

    private Listener<String> mListener;

    public StringRequest(int method, String   url, Listener<String> listener,

            ErrorListener errorListener) {

        super(method, url, errorListener);

        mListener = listener;

    }

    @Override

    protected void onFinish() {

        super.onFinish();

        mListener = null;

    }

    @Override

    protected void deliverResponse(String response) {

        if (mListener != null) {

            mListener.onResponse(response);

        }

    }

    /**

    * 解析网络请求返回数据

    */

    @Override

    protected Response<String> parseNetworkResponse(NetworkResponse response) {

        String parsed;

        try {

            parsed = new String(response.data, HttpHeaderParser.parseCharset(response.headers));

        } catch (UnsupportedEncodingException e) {

            parsed = new String(response.data);

        }

        return Response.success(parsed, HttpHeaderParser.parseCacheHeaders(response));

    }

}

若我们想要自定义一个XML文件的XmlRequest,利用XmlPullParserFactory和XmlPullParser去将返回的xml数据进行解析:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

/**

 * XmlRequest

 */

public class XmlRequest extends Request<XmlPullParser> {

    private final Response.Listener<XmlPullParser>   mListener;

    public XmlRequest(int method, String url, Response.Listener<XmlPullParser> listener,

                      Response.ErrorListener errorListener) {

        super(method, url, errorListener);

        mListener = listener;

    }

    public XmlRequest(String url, Response.Listener<XmlPullParser> listener, Response.ErrorListener errorListener) {

          this(Method.GET, url,   listener, errorListener);

    }

    @Override

    protected Response<XmlPullParser>   parseNetworkResponse(NetworkResponse response) {

        try {

            String xmlString = new String(response.data,

                    HttpHeaderParser.parseCharset(response.headers));

            XmlPullParserFactory factory =   XmlPullParserFactory.newInstance();

            XmlPullParser xmlPullParser =   factory.newPullParser();

            xmlPullParser.setInput(new StringReader(xmlString));

            return Response.success(xmlPullParser,   HttpHeaderParser.parseCacheHeaders(response));

        } catch (UnsupportedEncodingException   e) {

            return Response.error(new ParseError(e));

        } catch (XmlPullParserException e) {

            return Response.error(new ParseError(e));

        }

    }

    @Override

    protected void   deliverResponse(XmlPullParser response) {

        mListener.onResponse(response);

    }

}

XmlRequest的使用方法和Volley自带的Request差不多.

1.4 取消请求Request

当Activity销毁时,我们可能需要取消一些请求,这时候可以根据在创建Request时,为Request添加的Tag来取消对应的请求,在onDestroy()方法中填写如下代码:

1

2

3

4

5

6

7

8

9

/**

  * 为request设置请求标签

  */

 request.setTag("JSONArrayRequest_GET");

 @Override

 protected void onDestroy() {

     super.onDestroy();

     AppApplication.getRequestQueue().cancelAll("JSONArrayRequest_GET");

 }

或者若需要取消属于Activity中全部的请求,那么可以为所有属于该Activity的Request添加同样的Tag.
RequestQueue#cancelAll还有另一种重载形式,可以传入RequestFilter,自己指定一个过滤策略.

原文链接:http://www.apkbus.com/blog-719059-63045.html

0人推荐
随时随地看视频
慕课网APP