为了使用Volley,你必须添加android.permission.INTERNET
权限到你的manifest文件中。没有这个权限,你的app将无法访问网络。
使用Volley,一般为三步骤:
1. 创建一个RequestQueue对象。
2. 创建一个Request实现类对象。
3. 将Request实现类对象添加到RequestQueue里面。
Volley中Request的实现类默认有StringRequest,JsonObjectRequest,JsonArrayRequest,ImageRequest。就拿StringRequest来说:
rq = Volley.newRequestQueue(this); //第一步,创建一个RequestQueue对象
//第二步,创建一个StringRequest对象,下面为get请求方式
StringRequest stringRequest = new StringRequest("http://www.baidu.com", new Response.Listener<String>() {
@Override
public void onResponse(String response) {
text.setText(response);
// rq.stop(); //如果你仅仅是想做一个单次的请求并且不想要线程池一直保留,调用RequestQueue的stop方法。
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
}
});
stringRequest.addMarker("baidu-look"); //添加stringRequest生命周期的观察
stringRequest.setTag("baidu");
rq.add(stringRequest);
// stringRequest.cancel(); //请求取消,一般在activity的onstop中调用
// rq.cancelAll("baidu"); //请求队列取消有baidu这个tag的请求,一般在activity的onstop中调用。
效果图:
一个RequestQueue需要两部分来支持它的工作:一部分是网络操作,用来传输请求,另外一个是用来处理缓存操作的Cache。在Volley的工具箱中包含了标准的实现方式:DiskBasedCache
提供了每个文件与对应响应数据一一映射的缓存实现。 BasicNetwork
提供了一个网络传输的实现,连接方式可以是AndroidHttpClient或者是 HttpURLConnection.
BasicNetwork
是Volley默认的网络操作实现方式。一个BasicNetwork必须使用HTTP Client进行初始化。这个Client通常是AndroidHttpClient 或者 HttpURLConnection:
- 对于app target API level低于API 9(Gingerbread)的使用AndroidHttpClient。在Gingerbread之前,HttpURLConnection是不可靠的。对于这个的细节,请参考Android's HTTP Clients。
- 对于API Level 9以及以上的,使用HttpURLConnection。
下面的代码片段演示了如何一步步建立一个RequestQueue:
RequestQueue mRequestQueue;
// Instantiate the cache
Cache cache = new DiskBasedCache(getCacheDir(), 1024 * 1024); // 1MB cap
// Set up the network to use HttpURLConnection as the HTTP client.
Network network = new BasicNetwork(new HurlStack());
// Instantiate the RequestQueue with the cache and network.
mRequestQueue = new RequestQueue(cache, network);
// Start the queue
mRequestQueue.start();
开启Request的生命周期观察,使用request.
addMarker(
)方法。并在命令行中:
- $adb shell
- $setprop log.tag.Volley VERBOSE
- logcat
08-04 09:59:49.383 2478-2478/com.example.volleytest D/Volley﹕ [1] MarkerLog.finish: (+0 ) [ 1] baidu-look
08-04 09:59:49.388 2478-2478/com.example.volleytest D/Volley﹕ [1] MarkerLog.finish: (+1 ) [ 1] add-to-queue
08-04 09:59:49.389 2478-2478/com.example.volleytest D/Volley﹕ [1] MarkerLog.finish: (+223 ) [1056] cache-queue-take
08-04 09:59:49.391 2478-2478/com.example.volleytest D/Volley﹕ [1] MarkerLog.finish: (+0 ) [1056] cache-miss
08-04 09:59:49.393 2478-2478/com.example.volleytest D/Volley﹕ [1] MarkerLog.finish: (+0 ) [1058] network-queue-take
08-04 09:59:49.395 2478-2478/com.example.volleytest D/Volley﹕ [1] MarkerLog.finish: (+93 ) [1058] network-http-complete
08-04 09:59:49.397 2478-2478/com.example.volleytest D/Volley﹕ [1] MarkerLog.finish: (+4 ) [1058] network-parse-complete
08-04 09:59:49.402 2478-2478/com.example.volleytest D/Volley﹕ [1] MarkerLog.finish: (+0 ) [1058] post-response
08-04 09:59:49.404 2478-2478/com.example.volleytest D/Volley﹕ [1] MarkerLog.finish: (+1719) [ 1] done
08-04 10:22:25.069 3252-3252/com.example.volleytest D/Volley﹕ [1] MarkerLog.finish: (+0 ) [ 1] baidu-look
08-04 10:22:25.070 3252-3252/com.example.volleytest D/Volley﹕ [1] MarkerLog.finish: (+0 ) [ 1] add-to-queue
08-04 10:22:25.071 3252-3252/com.example.volleytest D/Volley﹕ [1] MarkerLog.finish: (+1 ) [1083] cache-queue-take
08-04 10:22:25.072 3252-3252/com.example.volleytest D/Volley﹕ [1] MarkerLog.finish: (+36 ) [1083] cache-discard-canceled
在开发中,我们一般定义一个全局的单例RequestQueue。一个关键的概念是RequestQueue必须和Application context所关联的。而不是Activity的context。这确保了RequestQueue在你的app生命周期中一直存活,而不会因为activity的重新创建而重新创建RequestQueue。(例如,当用户旋转设备时)。
public class MySingleton {
private static MySingleton mInstance;
private RequestQueue mRequestQueue;
private static Context mCtx;
private MySingleton(Context context) {
mCtx = context;
mRequestQueue = getRequestQueue();
}
public static synchronized MySingleton getInstance(Context context) {
if (mInstance == null) {
mInstance = new MySingleton(context);
}
return mInstance;
}
public RequestQueue getRequestQueue() {
if (mRequestQueue == null) {
// getApplicationContext() is key, it keeps you from leaking the
// Activity or BroadcastReceiver if someone passes one in.
mRequestQueue = Volley.newRequestQueue(mCtx.getApplicationContext());
}
return mRequestQueue;
}
public <T> void addToRequestQueue(Request<T> req) {
getRequestQueue().add(req);
}
}
自定义Request:GsonRequest
public class GsonRequest<T> extends Request<T> {
private final Gson gson = new Gson();
private final Class<T> clazz;
private final Map<String, String> headers = new HashMap<String, String>();
private final Map<String,String> postParams = new HashMap<String, String>();
private final Response.Listener<T> listener;
/*
* 设置访问自己服务器时必须传递的参数,密钥等
*/
{
headers.put("APP-Key", "LBS-AAA");
headers.put("APP-Secret", "ad12msa234das232in");
}
/**
* Make a GET request and return a parsed object from JSON.
*
* @param url URL of the request to make
* @param clazz Relevant class object, for Gson's reflection
* @param headers Map of request headers
*/
public GsonRequest(int method,String url, Class<T> clazz, Map<String, String> headers,Map<String, String> postParams,
Response.Listener<T> listener, Response.ErrorListener errorListener) {
super(method, url, errorListener);
this.clazz = clazz;
if(headers != null) {
this.headers.putAll(headers);
}
if(postParams != null) {
this.postParams.putAll(postParams);
}
this.listener = listener;
}
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
String message = "";
Iterator iter = headers.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry entry = (Map.Entry) iter.next();
String key = (String) entry.getKey();
String val = (String) entry.getValue();
message += key + "=" + val + "&";
}
if(headers.size() != 0){
message = message.substring(0,message.length()-1);
}
L.d("Headers",message);
return headers != null ? headers : super.getHeaders();
}
@Override
protected Map<String, String> getParams() throws AuthFailureError {
String message = "";
Iterator iter = postParams.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry entry = (Map.Entry) iter.next();
String key = (String) entry.getKey();
String val = (String) entry.getValue();
message += key + "=" + val + "&";
}
if(postParams.size() != 0){
message = message.substring(0,message.length()-1);
}
L.d("PostParams",message);
return postParams != null ? postParams : super.getParams();
}
@Override
protected void deliverResponse(T response) {
listener.onResponse(response);
}
@Override
protected Response<T> parseNetworkResponse(NetworkResponse response) {
try {
String json = new String(
response.data,
HttpHeaderParser.parseCharset(response.headers));
return Response.success(
gson.fromJson(json, clazz),
HttpHeaderParser.parseCacheHeaders(response));
} catch (UnsupportedEncodingException e) {
return Response.error(new ParseError(e));
} catch (JsonSyntaxException e) {
return Response.error(new ParseError(e));
}
}
}
主要就是重写parseNetworkResponse方法和deliverResponse方法。参照JsonObjectRequest来写。如果是post方式提交数据,就会调用getParams()来提交参数,getHeaders()方法是任何Request都会调用。getParams()和getHeaders()加log是方便排错。
Activity中代码:
rq = Volley.newRequestQueue(this);
HashMap<String,String> postParams = new HashMap<String, String>();
postParams.put("param1","value1");
postParams.put("param2", "value2");
GsonRequest<User> gsonRequest = new GsonRequest<User>(Request.Method.POST,
"http://192.168.1.100:8080/demo/WeatherServlet", User.class,
null ,postParams , new Response.Listener<User>() {
@Override
public void onResponse(User response) {
text.setText(response.getName());
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
text.setText(error.getMessage());
}
});
gsonRequest.addMarker("gson-request");
gsonRequest.setShouldCache(false); //不缓存
rq.add(gsonRequest);
服务器中的Servlet代码:
public class WeatherServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public WeatherServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String json = "{'name':'kedou','password':'123456'}";
response.setContentType("text/plain;charset=utf-8");
response.getWriter().write(json);;
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
这里仅仅只是输出一个json的字符串。
activity中是post方式提交,log信息:
08-04 15:55:17.141 12816-12841/com.example.volleytest D/Headers﹕ APP-Secret=ad12msa234das232in&APP-Key=LBS-AAA
08-04 15:55:17.143 12816-12841/com.example.volleytest D/PostParams﹕ param1=value1¶m2=value2
如果是get方式提交只会有Headers信息。
3.https://github.com/smanikandan14/Volley-demo中的说明
源码:http://yunpan.cn/cdjDJcINpnzXq (提取码:17bc)