Volley是Google于2013年推出的网络通信框架,集AsyncHttpClient和Universal-Image-Loader的优点于一身,对于数据量不大且需要频繁通信的网络请求操作可谓是及时雨,他的扩展性也非常好,可以重写Request类以实现自己的需求,所以非常推荐大家在合适的情景下使用这个框架。
Volley的官方地址:https://android.googlesource.com/platform/frameworks/volley
我使用的是git上面2015年8月份提交的代码。
下面详细介绍Volley的使用方法
1.工具类VolleyUtils,里面主要包含了String类型、JSON类型以及图片的Http请求方法总共7种,详细如下:
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import com.android.volley.AuthFailureError;
import com.android.volley.Request.Method;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.ImageLoader.ImageListener;
import com.android.volley.toolbox.JsonArrayRequest;
import com.android.volley.toolbox.JsonObjectRequest;
import com.android.volley.toolbox.StringRequest;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import com.google.gson.reflect.TypeToken;
import android.content.Context;
import android.widget.ImageView;
/**
* 代理模式,也可以作为Model(MVC),具体方法自行添加
*
* @author gaoruan
*/
public class VolleyUtils {
private static VolleyUtils volleyUtils;
private static RequestQueue requestQueue;
private static Context mContext;
public VolleyUtils() {
// TODO Auto-generated constructor stub
}
public static VolleyUtils getInstance(Context mContext, RequestQueue requestQueue) {
VolleyUtils.mContext = mContext;
VolleyUtils.requestQueue = requestQueue;
if (volleyUtils == null) {
volleyUtils = new VolleyUtils();
}
return volleyUtils;
}
// 字符串类型GET
public static StringRequest sHttpGet(String url) {
StringRequest stringRequest = new StringRequest(url, new Response.Listener<String>() {
@Override
public void onResponse(String arg0) {
// TODO Auto-generated method stub
LogUtils.e(arg0);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError arg0) {
// TODO Auto-generated method stub
LogUtils.e(arg0.getMessage());
}
});
return stringRequest;
}
// 字符串类型POST,链接必须支持post方式
public static StringRequest sHttpPost(String url) {
// 指定Method.POST当然也可以指定Method.GET
StringRequest stringRequest = new StringRequest(Method.POST, url, new Response.Listener<String>() {
@Override
public void onResponse(String arg0) {
// TODO Auto-generated method stub
LogUtils.e(arg0);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError arg0) {
// TODO Auto-generated method stub
LogUtils.e(arg0.getMessage());
}
}) {
// 设置post参数
@Override
protected Map<String, String> getParams() throws AuthFailureError {
// TODO Auto-generated method stub
Map<String, String> map = new HashMap<String, String>();
map.put("key", "value");
return super.getParams();
}
};
return stringRequest;
}
// JsonObject类型GET
public static JsonObjectRequest jsonoHttpGet(String url) {
JSONObject jsonObject = new JSONObject();
//
// if (jsonObject == null) {
// // 默认为get方式
// } else {
// // 默认为post方式
// }
//
// 此处使用GET方式发送请求
jsonObject = null;
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(url, jsonObject,
new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject arg0) {
// TODO Auto-generated method stub
List<MWeather> list = new ArrayList<MWeather>();
Type type = new TypeToken<List<MWeather>>() {
}.getType();
Gson gson = new Gson();
try {
list = gson.fromJson(arg0.getJSONObject("data").getJSONArray("forecast").toString(), type);
} catch (JsonSyntaxException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String mWeathers = gson.toJson(list);
LogUtils.e(mWeathers);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError arg0) {
// TODO Auto-generated method stub
LogUtils.e(arg0.getMessage());
}
});
return jsonObjectRequest;
}
// JsonObject类型POST,链接必须支持post方式
public static JsonObjectRequest jsonoHttpPost(String url) throws JSONException {
// 此处的jsonObject被指定为post参数
MWeather mWeather = new MWeather();
mWeather.setCitykey("101010100");
// 搭配GSON非常好用
Gson gson = new Gson();
String mJson = gson.toJson(mWeather);
// LogUtils.e(mJson);
// 指定Method.POST当然也可以指定Method.GET
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Method.POST, url, new JSONObject(mJson),
new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject arg0) {
// TODO Auto-generated method stub
LogUtils.e(arg0.toString());
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError arg0) {
// TODO Auto-generated method stub
LogUtils.e(arg0.getMessage());
}
});
return jsonObjectRequest;
}
// JsonArray类型GET
public static JsonArrayRequest jsonaHttpGet(String url) {
JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(url, new Response.Listener<JSONArray>() {
@Override
public void onResponse(JSONArray arg0) {
// 必须返回JSONArray
LogUtils.e(arg0.toString());
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError arg0) {
// TODO Auto-generated method stub
LogUtils.e(arg0.getMessage());
}
});
return jsonArrayRequest;
}
// JsonArray类型POST,链接必须支持post方式
public static JsonArrayRequest jsonaHttpPost(String url) throws JSONException {
// 此处的jsonObject被指定为post参数
MWeather mWeather = new MWeather();
mWeather.setCitykey("101010100");
// 搭配GSON非常好用
Gson gson = new Gson();
String mJson = gson.toJson(mWeather);
JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(Method.POST, url, new JSONArray(mJson),
new Response.Listener<JSONArray>() {
@Override
public void onResponse(JSONArray arg0) {
// TODO Auto-generated method stub
// 必须返回JSONArray
LogUtils.e(arg0.toString());
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError arg0) {
// TODO Auto-generated method stub
LogUtils.e(arg0.getMessage());
}
});
return jsonArrayRequest;
}
public static ImageListener imageHttp(ImageView view, int defaultImageResId, int errorImageResId) {
ImageListener imageListener = ImageLoader.getImageListener(view, defaultImageResId, errorImageResId);
return imageListener;
}
}
2.工具类MImageCache,这个类是ImageLoader加载网络图片用到的一个图片缓存类,继承自com.android.volley.toolbox.ImageLoader.ImageCache,详细如下:
import com.android.volley.toolbox.ImageLoader.ImageCache;
import android.graphics.Bitmap;
import android.support.v4.util.LruCache;
public class MImageCache implements ImageCache {
private LruCache<String, Bitmap> cache;
public MImageCache() {
cache = new LruCache<String, Bitmap>(8 * 1024 * 1024) {
@Override
protected int sizeOf(String key, Bitmap bitmap) {
return bitmap.getRowBytes() * bitmap.getHeight();
}
};
}
@Override
public Bitmap getBitmap(String arg0) {
// TODO Auto-generated method stub
return cache.get(arg0);
}
@Override
public void putBitmap(String arg0, Bitmap arg1) {
// TODO Auto-generated method stub
cache.put(arg0, arg1);
}
}
3.工具类LogUtils,这个类是自定义的一个log日志类,详细如下:
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Date;
import android.annotation.SuppressLint;
import android.util.Log;
public class LogUtils {
private final static String TAG = "msg";
private final static boolean isDebug = true;
private final static boolean isWF = false;
@SuppressLint("SdCardPath")
final static String sdcard = "/mnt/sdcard/";
final static String logFile = "syslog.txt";
final static File file = new File(sdcard);
@SuppressWarnings("deprecation")
static private void writeToFile(String str) {
if (isWF)
return;
try {
synchronized (file) {
if (file.canWrite()) {
Date curDate = new Date(System.currentTimeMillis());
FileWriter fileWriter = new FileWriter(sdcard + logFile, true);
fileWriter
.write(curDate.getHours() + ":" + curDate.getMinutes() + ":" + curDate.getSeconds() + " ");
fileWriter.write(str + "\n");
fileWriter.flush();
fileWriter.close();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
private static String StackTrace(int n) {
// long id = Thread.currentThread().getId();
String file = Thread.currentThread().getStackTrace()[4 + n].getFileName();
int line = Thread.currentThread().getStackTrace()[4 + n].getLineNumber();
String method = Thread.currentThread().getStackTrace()[4 + n].getMethodName();
return file + "->" + method + " " + ":" + line + " ";
}
static public void d(String msg, int n) {
if (isDebug) {
String log = StackTrace(n) + msg;
Log.d(TAG, log);
writeToFile(log);
}
}
static public void d(String msg) {
if (isDebug) {
String log = StackTrace(0) + msg;
Log.d(TAG, log);
writeToFile(log);
}
}
static public void i(String msg) {
if (isDebug) {
String log = StackTrace(0) + msg;
Log.i(TAG, log);
writeToFile(log);
}
}
static public void e(String msg) {
if (isDebug) {
String log = StackTrace(0) + msg;
Log.e(TAG, log);
writeToFile(log);
}
};
}
4.MWeather类,这个类是自定义的一个JavaBean,主要是解析天气预报网址的Json时用到的,详细如下:
public class MWeather {
private String citykey;
private String aqi;
private String desc;
private String status;
private String high;
private String fl;
private String date;
private String low;
private String type;
private String fx;
private String wendu;
private String ganmao;
private String city;
public String getCitykey() {
return citykey;
}
public void setCitykey(String citykey) {
this.citykey = citykey;
}
public String getAqi() {
return aqi;
}
public void setAqi(String aqi) {
this.aqi = aqi;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getHigh() {
return high;
}
public void setHigh(String high) {
this.high = high;
}
public String getFl() {
return fl;
}
public void setFl(String fl) {
this.fl = fl;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getLow() {
return low;
}
public void setLow(String low) {
this.low = low;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getFx() {
return fx;
}
public void setFx(String fx) {
this.fx = fx;
}
public String getWendu() {
return wendu;
}
public void setWendu(String wendu) {
this.wendu = wendu;
}
public String getGanmao() {
return ganmao;
}
public void setGanmao(String ganmao) {
this.ganmao = ganmao;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
@Override
public String toString() {
return "MWeather [citykey=" + citykey + ", aqi=" + aqi + ", desc=" + desc + ", status=" + status + ", high="
+ high + ", fl=" + fl + ", date=" + date + ", low=" + low + ", type=" + type + ", fx=" + fx + ", wendu="
+ wendu + ", ganmao=" + ganmao + ", city=" + city + "]";
}
}
5.MainActivity类,这个类是主Activity,主要是调用工具类里面的方法,详细如下:
import com.android.volley.RequestQueue;
import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.NetworkImageView;
import com.android.volley.toolbox.Volley;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.widget.ImageView;
public class MainActivity extends Activity {
public static Context mContext;
private static RequestQueue requestQueue;
private static ImageLoader imageLoader;
private ImageView imageView1;
private NetworkImageView imageView2;
public static final String MURL = "http://www.battlenet.com.cn/zh/";
public static final String MWEATHER = "http://wthrcdn.etouch.cn/weather_mini?";// 天气预报
public static final String CITYKEY = "citykey=101010100";
// 以下两个网址来自战网
public static final String IMAGEURLF = "http://cms-origin-cn.battle.net/cms/carousel_header/og/OGBTDYRA7KZB1449121751020.jpg";
public static final String IMAGEURLS = "http://cms-origin-cn.battle.net/cms/gallery/wf/WFH5OT2327L61446861473547.jpg";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mContext = this;
imageView1 = (ImageView) findViewById(R.id.imageView1);
imageView2 = (NetworkImageView) findViewById(R.id.imageView2);
VolleyUtils.getInstance(mContext, requestQueue);
/**
* 获取String类型response********
* getRequestQueue().add(VolleyUtils.sHttpGet(MURL));
* getRequestQueue().add(VolleyUtils.sHttpPost(MURL));
*/
/**
* 获取JSONObject类型response
* getRequestQueue().add(VolleyUtils.jsonoHttpGet(MWEATHER + CITYKEY));
* getRequestQueue().add(VolleyUtils.jsonoHttpPost(MWEATHER));
*/
/**
* 获取JSONArray类型response
* getRequestQueue().add(VolleyUtils.jsonaHttpGet(MWEATHER + CITYKEY));
* getRequestQueue().add(VolleyUtils.jsonaHttpPost(MWEATHER));
*/
/**
* 获取网络图片********************************************
* getImageLoader().get(IMAGEURLF, VolleyUtils.imageHttp(imageView1,
* R.drawable.og_wow, R.drawable.ic_launcher));
* *******************************************************
* imageView2.setImageUrl(IMAGEURLS, getImageLoader());
*/
}
// 单例
private RequestQueue getRequestQueue() {
if (requestQueue == null) {
requestQueue = Volley.newRequestQueue(mContext);
}
return requestQueue;
}
// 单例
private ImageLoader getImageLoader() {
if (requestQueue == null) {
requestQueue = Volley.newRequestQueue(mContext);
}
if (imageLoader == null) {
imageLoader = new ImageLoader(getRequestQueue(), new MImageCache());
}
return imageLoader;
}
@Override
public void onStop() {
// 取消未完成的请求
// mRequestQueue.cancelAll( new RequestFilter() {})
getRequestQueue().cancelAll(this);
}
6.Activity用到的xml文件,详细如下:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.ruan.test.MainActivity" >
<ImageView
android:id="@+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:src="@drawable/ic_launcher" />
<com.android.volley.toolbox.NetworkImageView
android:id="@+id/imageView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/imageView1"
android:layout_marginTop="50dp"
android:layout_centerHorizontal="true"
android:src="@drawable/ic_launcher" />
</RelativeLayout>
总结:
1、需要注意Volley对于JSON格式的返回操作及网络图片加载非常方便,但是并不适合大流量譬如下载、流媒体操作等网络数据量比较大的情景下使用
2、其中RequestQueue和ImageLoader都是单例的,注意尽量不要重复创建
3、Activity销毁的时候需要结束这些请求,因为这些请求都是可控的
4、Volley支持继承Request以实现适合自己项目的网络编程
5、解析JSON的时候用到了GSON封装包,配合Volley非常好用,推荐使用
暂时总结这么多,遇到问题再继续总结。
源码下载:
我是链接,请点我下载