android开发,volley的二次封装和使用
程序员文章站
2024-03-15 19:20:30
...
先简单介绍一下。Android SDK中提供了HttpClient 和 HttpUrlConnection两种方式用来处理网络操作,但应用起来比较繁琐,需要我们编写大量的代码处理很多东西:缓存,Header等等;
而Volley框架就是为解决这些而生的,它与2013年Google I/O大会上被提出:使得Android应用网络操作更方便更快捷;抽象了底层Http Client等实现的细节,让开发者更专注与产生RESTful Request。另外,Volley在不同的线程上异步执行所有请求而避免了阻塞主线程。
Volley到底有哪些特点呢?
- 自动调度网络请求
- 多个并发的网络连接
- 通过使用标准的HTTP缓存机制保持磁盘和内存响应的一致
- 支持请求优先级
- 支持取消请求的强大API,可以取消单个请求或多个
- 易于定制
- 健壮性:便于正确的更新UI和获取数据
- 包含调试和追踪工具
好,废话结束了。一起看看怎么使用volley吧。volley本身使用是比较容易的,但我们做项目过程中往往需要再封装一下,以便于更好的统一使用,本文就是对volley的二次封装,便于开发过程中调用。你也可以根据你的需要进行一些改造。需要注意一点的是,volley只适合数据量比较小,比较频繁的请求。对数据量比较大的,比如下载文件等不太合适。
首先使用volley需要导入相关的jar包,只需要一个jar而已,可以到maven下载:http://mvnrepository.com/artifact/com.mcxiaoke.volley/library/1.0.19
在你的android工程的 values/strings.xml 文件添加下面几个元素,是用来提示用的:
<string name="no_internet">无网络连接~!</string>
<string name="generic_server_down">连接服务器失败~!</string>
<string name="generic_error">网络异常,请稍后再试~!</string>
下面看看3个关键的类,直接放到工程里面就可以使用,里面有详细的注释
Volley异常帮助类
package com.kokjuis.travel.volley;
import java.util.HashMap;
import java.util.Map;
import android.content.Context;
import com.android.volley.AuthFailureError;
import com.android.volley.NetworkError;
import com.android.volley.NetworkResponse;
import com.android.volley.NoConnectionError;
import com.android.volley.ServerError;
import com.android.volley.TimeoutError;
import com.android.volley.VolleyError;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.kokjuis.travel.R;
//以下是Volley的异常列表:
//AuthFailureError:如果在做一个HTTP的身份验证,可能会发生这个错误。
//NetworkError:Socket关闭,服务器宕机,DNS错误都会产生这个错误。
//NoConnectionError:和NetworkError类似,这个是客户端没有网络连接。
//ParseError:在使用JsonObjectRequest或JsonArrayRequest时,如果接收到的JSON是畸形,会产生异常。
//SERVERERROR:服务器的响应的一个错误,最有可能的4xx或5xx HTTP状态代码。
//TimeoutError:Socket超时,服务器太忙或网络延迟会产生这个异常。默认情况下,Volley的超时时间为2.5秒。如果得到这个错误可以使用RetryPolicy。
/**
* volley异常帮助类
*
* @author:gj
* @date: 2016/5/17
* @time: 15:05
**/
public class VolleyErrorHelper {
/**
* Returns appropriate message which is to be displayed to the user against
* the specified error object.
*
* @param error
* @param context
* @return
*/
public static String getMessage(Object error, Context context) {
if (error instanceof TimeoutError) {
return context.getResources().getString(
R.string.generic_server_down);
} else if (isServerProblem(error)) {
return handleServerError(error, context);
} else if (isNetworkProblem(error)) {
return context.getResources().getString(R.string.no_internet);
}
return context.getResources().getString(R.string.generic_error);
}
/**
* Determines whether the error is related to network
*
* @param error
* @return
*/
private static boolean isNetworkProblem(Object error) {
return (error instanceof NetworkError)
|| (error instanceof NoConnectionError);
}
/**
* Determines whether the error is related to server
*
* @param error
* @return
*/
private static boolean isServerProblem(Object error) {
return (error instanceof ServerError)
|| (error instanceof AuthFailureError);
}
/**
* Handles the server error, tries to determine whether to show a stock
* message or to show a message retrieved from the server.
*
* @param err
* @param context
* @return
*/
private static String handleServerError(Object err, Context context) {
VolleyError error = (VolleyError) err;
NetworkResponse response = error.networkResponse;
if (response != null) {
switch (response.statusCode) {
case 404:
case 422:
case 401:
try {
// server might return error like this { "error":
// "Some error occured" }
// Use "Gson" to parse the result
HashMap<String, String> result = new Gson().fromJson(
new String(response.data),
new TypeToken<Map<String, String>>() {
}.getType());
if (result != null && result.containsKey("error")) {
return result.get("error");
}
} catch (Exception e) {
e.printStackTrace();
}
// invalid request
return error.getMessage();
default:
return context.getResources().getString(
R.string.generic_server_down);
}
}
return context.getResources().getString(R.string.generic_error);
}
}
volley请求类
package com.kokjuis.travel.volley;
import android.util.Log;
import com.android.volley.AuthFailureError;
import com.android.volley.DefaultRetryPolicy;
import com.android.volley.NetworkResponse;
import com.android.volley.ParseError;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.Response.Listener;
import com.android.volley.RetryPolicy;
import com.android.volley.toolbox.HttpHeaderParser;
import com.kokjuis.travel.comm.MyApplication;
import com.kokjuis.travel.utils.GsonUtil;
import com.kokjuis.travel.utils.RsaEncryptUtil;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
/**
* 类描述: 创建人:kokJuis 创建时间:2016/3/8 14:07 修改备注:
* <p>
* VolleyRequest vr=new VolleyRequest(Request.Method.POST,
* WebLinksUtil.login,params,new Response.Listener() {
*
* @Override public void onResponse(Object o) {
* <p>
* Log.v("--->>>>-----",o.toString()); } }, new
* Response.ErrorListener() {
* @Override public void onErrorResponse(VolleyError volleyError) {
* Log.v("--->>>>-----",volleyError.getMessage()); } });
* <p>
* VolleyUtil.getVolleyUtil(this).addToRequestQueue(vr,TAG);
*/
public class VolleyRequest extends Request<String> {
private static final String TAG = "VolleyRequest";
//请求监听
private final Listener<Object> listener;
//保存请求参数
private static Map<String, String> params;
// 构造方法
private VolleyRequest(int method, String url,
Response.Listener<Object> listener,
Response.ErrorListener errorListener) {
super(method, url, errorListener);
this.listener = listener;
}
/**
* post请求
*
* @author:gj
* @date: 2016/5/17
* @time: 15:13
**/
public static VolleyRequest post(String url, Map<String, String> params,
Response.Listener<Object> listener,
Response.ErrorListener errorListener) {
//下面只是打印出完整的URL,便于调试
if (params != null) {
Log.v(TAG, "params:" + params);
String str = "";
for (Map.Entry<String, String> entry : params.entrySet()) {
str += entry.getKey() + "=" + entry.getValue() + "&";
}
String tmp = url + "?"
+ str.substring(0, str.length()-1);
Log.v(TAG, "url:" + tmp);
//把参数赋值
VolleyRequest.params = data;
}
return new VolleyRequest(Method.POST, url, listener, errorListener);
}
/**
* get请求
*
* @author:gj
* @date: 2016/5/17
* @time: 15:13
**/
public static VolleyRequest get(String url, Map<String, String> params,
Response.Listener<Object> listener,
Response.ErrorListener errorListener) {
//下面只是打印出完整的URL,便于调试
if (params != null) {
Log.v(TAG, "params:" + params);
String str = "";
for (Map.Entry<String, String> entry : params.entrySet()) {
str += entry.getKey() + "=" + entry.getValue() + "&";
}
url += "?"
+ str.substring(0, str.length()-1);
Log.v(TAG, "url:" + url);
//这里可以根据你的要求改造
}
return new VolleyRequest(Method.GET, url, listener, errorListener);
}
/**
* 请求返回
*
* @author:gj
* @date: 2017/5/17
* @time: 15:24
**/
@Override
protected Response<String> parseNetworkResponse(
NetworkResponse networkResponse) {
String parsed;
try {
//这里可以获取返回的header信息,可以把想要的东西提取
Map<String, String> responseHeaders = networkResponse.headers;
String Token = responseHeaders.get("Token");
if (Token != null) {
Log.v(TAG, "Token:" + Token);
}
parsed = new String(networkResponse.data,
HttpHeaderParser.parseCharset(networkResponse.headers));
return Response.success(parsed,
HttpHeaderParser.parseCacheHeaders(networkResponse));
} catch (UnsupportedEncodingException e) {
// parsed = new String(networkResponse.data);
return Response.error(new ParseError(e));
} catch (Exception e) {
return Response.error(new ParseError(e));
}
}
/**
* 监听返回
*
* @author:gj
* @date: 2017/5/17
* @time: 15:20
**/
@Override
protected void deliverResponse(String response) {
listener.onResponse(response);
}
/**
* 请求设置参数
*
* @author:gj
* @date: 2017/5/17
* @time: 15:20
**/
@Override
protected Map<String, String> getParams() throws AuthFailureError {
return params == null ? super.getParams() : params;
}
/**
* 设置请求头
*
* @author:gj
* @date: 2017/5/17
* @time: 15:20
**/
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
//在这个方法里面,可以设置请求头的参数,比如Charset,Content-Type,也可以设置一些你想要的值
HashMap<String, String> localHashMap = new HashMap<String, String>();
localHashMap.put("Charset", "UTF-8");
localHashMap.put("Content-Type", "application/x-www-form-urlencoded");
// localHashMap.put("Accept-Encoding", "gzip,deflate");
//设置请求的token
localHashMap.put("Token", "");
return localHashMap;
}
/**
* 设置请求超时时间
*
* @author:gj
* @date: 2017/5/17
* @time: 15:22
**/
@Override
public RetryPolicy getRetryPolicy() {
// 设置超时时间为5秒。
RetryPolicy retryPolicy = new DefaultRetryPolicy(5000, 0,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT);
return retryPolicy;
}
@Override
public void setRetryPolicy(RetryPolicy retryPolicy) {
RetryPolicy Policy = new DefaultRetryPolicy(5000, 0,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT);
super.setRetryPolicy(Policy);
}
}
volley请求工具类
package com.kokjuis.travel.volley;
import android.content.Context;
import android.graphics.Bitmap;
import android.text.TextUtils;
import android.util.LruCache;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.Volley;
/**
* 创建人:kokJuis 创建时间:2016/3/8 14:57 备注:
*/
public class VolleyUtil {
public static final String TAG = "VolleyUtil";
private static VolleyUtil volleyUti;
private RequestQueue mRequestQueue;
private ImageLoader mImageLoader;
private Context mContext;
/**
* 单例模式。
*
* @param context
*/
private VolleyUtil(Context context) {
this.mContext = context;
mRequestQueue = getRequestQueue();
mImageLoader = new ImageLoader(mRequestQueue,
new ImageLoader.ImageCache() {
private final LruCache<String, Bitmap> cache = new LruCache<String, Bitmap>(
20);
@Override
public Bitmap getBitmap(String url) {
return cache.get(url);
}
@Override
public void putBitmap(String url, Bitmap bitmap) {
cache.put(url, bitmap);
}
});
}
public static synchronized VolleyUtil getVolleyUtil(Context context) {
if (volleyUti == null) {
volleyUti = new VolleyUtil(context);
}
return volleyUti;
}
// 获取一个请求队列
public RequestQueue getRequestQueue() {
if (mRequestQueue == null) {
mRequestQueue = Volley.newRequestQueue(mContext
.getApplicationContext());
}
return mRequestQueue;
}
// 把请求添加到队列里面
public <T> void addToRequestQueue(Request<T> req, String tag) {
// 设置一个标记,便于取消队列里的请求
req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);
getRequestQueue().add(req);
}
// 取消指定请求
public void cancelRequest(String tag) {
if (mRequestQueue != null) {
mRequestQueue.cancelAll(tag);
}
}
public ImageLoader getImageLoader() {
return mImageLoader;
}
}
使用:
private void getUserData(String account) {
Map<String, String> params = new HashMap<String, String>();
params.put("account", account);
//创建一个get请求
VolleyRequest vr = VolleyRequest.get(
ApiList.findByAccounts_api, params,
new Listener<Object>() {
@Override
public void onResponse(Object arg0) {
if (arg0 != null) {
//请求成功
Log.v(TAG, arg0.toString());
}
}
}, new ErrorListener() {
@Override
public void onErrorResponse(VolleyError arg0) {
Log.e(TAG, arg0.getMessage());//请求失败,打印失败信息
}
});
//把请求添加到请求队列才会真正的请求网络,第一参数就是创建的请求,第二个是请求的标记,可以通过这个标记取消请求
VolleyUtil.getVolleyUtil(this).addToRequestQueue(vr, TAG);
}
@Override
protected void onDestroy() {
super.onDestroy();
//取消请求
VolleyUtil.getVolleyUtil(this).cancelRequest(TAG);
}
上一篇: Junit之Test测试
下一篇: MVP开发模式解析
推荐阅读
-
android开发,volley的二次封装和使用
-
Android开发中使用Volley库发送HTTP请求的实例教程
-
Android开发中使用sqlite实现新闻收藏和取消收藏的功能
-
Android开发中使用Volley库发送HTTP请求的实例教程
-
Android开发中使用sqlite实现新闻收藏和取消收藏的功能
-
Android开发之机顶盒上gridview和ScrollView的使用详解
-
Android OkHttp的简单使用和封装详解
-
Android的ListView,使用封装和MVC的设计模式
-
Android开发中使用mms模块收发单卡和双卡短信的教程
-
Android OkHttp的简单使用和封装详解