Volley简介及现状
- Volley是谷歌2013年在I/O大会期间推出的网络库。开发Volley是因为在Android SDK中缺乏一个用户体验良好的网络加载类。
- Volley自身的特点在于:适合去进行数据量不大,但通信频繁的网络操作;而对于大数据量的网络操作,例如上传/下载文件,其表现就不怎么给力了。
由于OkHttp的优异的表现和性能,Volley使用量逐渐减少,更不要说OkHttp的升级版Retrofit的异军突起。
但是作为一款优秀的网络框架,我们还是要简单了解一下其使用的。
本文就结合demo简单介绍一下如何Volley使用。
添加依赖
有趣的一点是,与其它很多常见的开源库的导入不同,Volley自身是没有提供官方的Maven或者说Jcenter Repository的。
Android Studio可以直接工程或者项目的build.gradle下添加依赖即可:
dependencies {
...
compile 'com.mcxiaoke.volley:library:1.0.19'
...
}
使用介绍
- 常见的request请求类型有三种:StringRequest、ImageRequest、JsonRequest
- 常见的请求方式有:默认是0,即get请求
/**
* Supported request methods.
*/
public interface Method {
int DEPRECATED_GET_OR_POST = -1;
int GET = 0;
int POST = 1;
int PUT = 2;
int DELETE = 3;
int HEAD = 4;
int OPTIONS = 5;
int TRACE = 6;
int PATCH = 7;
}
- RequestQueue会将多个HTTP请求缓存进队列,然后按照一定的算法分别去执行这些请求。
所以,通常我们很显然没有必要将这个东西在每次需要发起请求时都去new一次,可以将RequestQueue设计为单例来节约资源。 - 为request请求对象,设置一些必要的策略,如重试策略等。
- 将得到RequestQueue与Request对象,然后将request添加到请求队列中就可以了。
StringRequest请求类型
1.GET
public static void get(Context context, String url) {
RequestQueue requestQueue = Volley.newRequestQueue(this);
//因为默认请求方式为get,StringRequest()方法的第一个参数无需设置
StringRequest request = new StringRequest(url, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
Log.d(TAG, response);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.d(TAG, error.toString());
}
});
requestQueue.add(request);
}
2.POST
public static void post(Context context, String url, final Map<String, String> map) {
RequestQueue requestQueue = Volley.newRequestQueue(this);
//StringRequest()方法的第一个参数设置为Request.Method.POST,即post请求
StringRequest request = new StringRequest(Request.Method.POST, url, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
Log.d(TAG, response);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.d(TAG, error.toString());
}
}) {
@Override
protected Map<String, String> getParams() throws AuthFailureError {
return map;//请求参数Map类型
}
};
//对Request设置重试策略时,更改默认超时时间为5000
//由于重试策略,如果默认超时时间过短,请求参数过大,会出现请求参数重复上传的现象
request.setRetryPolicy(new DefaultRetryPolicy(5000, DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
requestQueue.add(request);
}
JsonRequest
JsonRequest顾名思义,就是说服务器响应的数据类型是JSON格式的,而对于其使用,与StringRequest是很相似的。
由于String与Json的转换时很简单的,所以两种方式任选其一即可。
JsonObjectRequest request = new JsonObjectRequest(url, new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
}
},null);
ImageRequest
从名字我们可以看到这个类显然就是为了图片专门封装的,相比StringRequest和JsonRequest稍有不同了。(JSON就只是指定了格式的文字而已)
但也是由于Volley本身封装的比较好,所以虽然不再是响应文字而是响应图片,但使用起来也很简单。
ImageRequest request = new ImageRequest(url, new Response.Listener<Bitmap>() {
@Override
public void onResponse(Bitmap response) {
//imageView.setImageBitmap(response);
}
},maxWidth,maxHeight,scaleType,decodeConfig,errListener);
maxWidth //图片最大宽度
maxHeight//图片最大高度
scaleType //指定图片缩放类型
ImageLoader
对于图片的下载显示,Volley还提供了一个相较ImageRequest更加强力一点的东东ImageLoader,关于其使用其实也不复杂。
/**
* 缓存策略根据url处理图片
* 将图片直接显示在ImageView上
* 比ImageRequest效率高
*
* @param context
* @param url
* @param view
*/
public static void ImageLoader(Context context, String url, ImageView view) {
if (requestQueue == null) {
requestQueue = getQueue(context.getApplicationContext());
}
final LruCache<String, Bitmap> mImageCache = new LruCache<String, Bitmap>(20);
ImageLoader.ImageCache imageCache = new ImageLoader.ImageCache() {
@Override
public Bitmap getBitmap(String s) {
return mImageCache.get(s);
}
@Override
public void putBitmap(String s, Bitmap bitmap) {
mImageCache.put(s, bitmap);
}
};
ImageLoader imageLoader = new ImageLoader(requestQueue, imageCache);
ImageLoader.ImageListener listener = ImageLoader.getImageListener(view, R.mipmap.ic_launcher, R.mipmap
.ic_launcher);
imageLoader.get(url, listener);
}
Demo
1.VolleyModel
- 使用单例模式获取RequestQueue对象
- 为了将获取的结果传递到View,使用接口传递
- 对于需要上传请求参数的post,必要时需要设置策略时间。
public class VolleyModel {
private static final String TAG = "VolleyModel";
private volatile static RequestQueue requestQueue;
/**
* 单例模式,双重校验锁
*
* @param context
* @return
*/
public static RequestQueue getQueue(Context context) {
if (requestQueue == null) {
synchronized (VolleyModel.class) {
if (requestQueue == null) {
requestQueue = Volley.newRequestQueue(context.getApplicationContext());
}
}
}
return requestQueue;
}
/**
* get请求
*
* @param context
* @param url 接口地址
* @param callBack 回调函数
*/
public static void get(Context context, String url, final ICallBack callBack) {
if (requestQueue == null) {
requestQueue = getQueue(context);
}
StringRequest request = new StringRequest(url, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
Log.d(TAG, response);
callBack.result(response);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.d(TAG, error.toString());
}
});
requestQueue.add(request);
}
/**
* post请求
*
* @param context
* @param url 接口地址
* @param map 请求参数
* @param callBack
*/
public static void post(Context context, String url, final Map<String, String> map, final ICallBack callBack) {
if (requestQueue == null) {
requestQueue = getQueue(context);
}
StringRequest request = new StringRequest(Request.Method.POST, url, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
Log.d(TAG, response);
callBack.result(response);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.d(TAG, error.toString());
}
}) {
@Override
protected Map<String, String> getParams() throws AuthFailureError {
return map;
}
};
//对Request设置重试策略时,更改默认超时时间为5000
//由于重试策略,如果默认超时时间过短,请求参数过大,会出现请求参数重复上传的现象
request.setRetryPolicy(new DefaultRetryPolicy(5000, DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
requestQueue.add(request);
}
/**
* image图片相关请求
*
* @param context
* @param url 图片地址
* @param callBack 接口回调
*/
public static void image(Context context, String url, final ICallBack callBack) {
if (requestQueue == null) {
requestQueue = getQueue(context);
}
ImageRequest request = new ImageRequest(url, new Response.Listener<Bitmap>() {
@Override
public void onResponse(Bitmap response) {
callBack.result(response);
}
}, 480, 600, ImageView.ScaleType.FIT_XY, Bitmap.Config.RGB_565, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.d(TAG, error.toString());
}
});
requestQueue.add(request);
}
/**
* 缓存策略根据url处理图片
* 将图片直接显示在ImageView上
* 比ImageRequest效率高
*
* @param context
* @param url
* @param view
*/
public static void ImageLoader(Context context, String url, ImageView view) {
if (requestQueue == null) {
requestQueue = getQueue(context.getApplicationContext());
}
final LruCache<String, Bitmap> mImageCache = new LruCache<String, Bitmap>(20);
ImageLoader.ImageCache imageCache = new ImageLoader.ImageCache() {
@Override
public Bitmap getBitmap(String s) {
return mImageCache.get(s);
}
@Override
public void putBitmap(String s, Bitmap bitmap) {
mImageCache.put(s, bitmap);
}
};
ImageLoader imageLoader = new ImageLoader(requestQueue, imageCache);
ImageLoader.ImageListener listener = ImageLoader.getImageListener(view, R.mipmap.ic_launcher, R.mipmap
.ic_launcher);
imageLoader.get(url, listener);
}
}
2.ICallBack
接口回调,在Model与View中传递结果。
public interface ICallBack {
void result(Object object);
}
3.xml布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="demon.volly.MainActivity">
<TextView
android:id="@+id/text1"
android:layout_width="match_parent"
android:layout_height="100dp"/>
<TextView
android:id="@+id/text2"
android:layout_width="match_parent"
android:layout_height="100dp"/>
<ImageView
android:id="@+id/image1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<ImageView
android:id="@+id/image2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
4.MainActivity
API免费测试接口:http://www.bejson.com/knownjson/webInterface/
public class MainActivity extends AppCompatActivity {
//京东获取单个商品价格接口:
String geturl = "http://p.3.cn/prices/mgets?skuIds=J_954086&type=1";
//阿里云根据地区名获取经纬度接口
String posturl = "http://gc.ditu.aliyun.com/geocoding";
//图片链接
String imageurl = "http://images.csdn.net/20150817/1.jpg";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final ImageView image1 = (ImageView) findViewById(R.id.image1);
final ImageView image2 = (ImageView) findViewById(R.id.image2);
final TextView text1 = (TextView) findViewById(R.id.text1);
final TextView text2 = (TextView) findViewById(R.id.text2);
VolleyModel.get(this, geturl, new ICallBack() {
@Override
public void result(Object object) {
String s = (String) object;
text1.setText(s);
}
});
Map<String, String> map = new HashMap<>();
map.put("a", "苏州市");
VolleyModel.post(this, posturl, map, new ICallBack() {
@Override
public void result(Object object) {
String s = (String) object;
text2.setText(s);
}
});
VolleyModel.image(this, imageurl, new ICallBack() {
@Override
public void result(Object object) {
Bitmap bitmap = (Bitmap) object;
image1.setImageBitmap(bitmap);
}
});
VolleyModel.ImageLoader(this, imageurl, image2);
}
}
5.效果图
Module代码下载
代码下载CSDN:http://download.csdn.net/download/demonliuhui/9953753
只看代码不下载GitHub:
https://github.com/DeMonLiu623/DeMonTest/tree/master/Volley
参考
http://blog.csdn.net/ghost_programmer/article/details/52333877