volley是google官方出的一个Android网络访问库,可以进行http访问和图片的网络异步获取(类似于imageloader)。
由于才刚开始练习面向对象编程,所以就想对volley进行初步封装根据自己的喜好来使用。
先说说volley的最基本用法:
在导入了jar后,在需要做网络访问的地方申请一个请求队列:
private RequestQueue mRequestQueue;
mRequestQueue = Volley.newRequestQueue(this);
一般在一个activity中只要一个请求队列,在需要访问网络时就new一个request实例再add到队列中就可以了。
建立一个StringRquest(是Request<T>的一个之类):
StringRequest myRequest = new StringRequest(Method.GET,url, new Listener<String>() {
@Override
public void onResponse(String arg0) {
// TODO Auto-generated method stub
Log.d("string request success linstener", arg0 + "");
}
}, new ErrorListener() {
@Override
public void onErrorResponse(VolleyError arg0) {
// TODO Auto-generated method stub
Log.d("string request error linstener", arg0.getMessage() + "");
}
});
这个是一个最简单的get方法请求。
还可以建立一个post方法请求:
StringRequest myRequest = new StringRequest(Method.POST,url, new Listener<String>() {
@Override
public void onResponse(String arg0) {
// TODO Auto-generated method stub
Log.d("string request success linstener", arg0 + "");
}
}, new ErrorListener() {
@Override
public void onErrorResponse(VolleyError arg0) {
// TODO Auto-generated method stub
Log.d("string request error linstener", arg0.getMessage() + "");
}
}){
@Override
protected Map<String, String> getParams() throws AuthFailureError {
// TODO Auto-generated method stub
Map<String, String> map = new HashMap<String, String>();
return map;
}
};
在post方法中,需要设置post所带的参数,就重载request的getParams方法,以map的形式输入。
最后就是把建立好的request实例add到队列中:
mRequestQueue.add(myRequest);
这样volley的基本使用就完成了。
到这里,就觉得要根据不同的请求每次new一个不同request,而且有时候还要重载各种方法,所以就打算做一个简单初步的封装使用。
最开始我先建立两个基类:
1,AbsRequest.java 这个类是Request的抽象(下面这个抽象的实现会详细说明):
public abstract class AbsRequest<T> extends Request<T> {
//父类函数
public AbsRequest(int method, String url, ErrorListener listener) {
super(method, url, listener);
}
//访问网络成功后返回的Response处理
@Override
protected abstract Response<T> parseNetworkResponse(NetworkResponse response) ;
//编辑头部需要带的信息
@Override
public abstract Map<String, String> getHeaders() throws AuthFailureError ;
//获取访问网络的方式get/post
@Override
public abstract int getMethod() ;
//获取需要访问的地址
@Override
public abstract String getUrl() ;
//获取访问网络需要带的参数
@Override
protected abstract Map<String, String> getParams() throws AuthFailureError ;
//访问网络成功返回后的操作
@Override
protected abstract void deliverResponse(T paramT);
}
2.RequestCallBack.java 这个是网络访问后对应的回调:
public abstract class RequestCallBack implements Response.Listener<String>,Response.ErrorListener{
public Response.Listener<String> mSuccessCallBack = new Listener<String>() {
@Override
public void onResponse(String arg0) {
// TODO Auto-generated method stub
RequestCallBack.this.onResponse(arg0);
}
};
public Response.ErrorListener mErrorCallBack = new ErrorListener() {
@Override
public void onErrorResponse(VolleyError arg0) {
// TODO Auto-generated method stub
RequestCallBack.this.onErrorResponse(arg0);
}
};
@Override
public abstract void onResponse(String arg0);
@Override
public abstract void onErrorResponse(VolleyError arg0);
}
然后,现在每一个网络请求都建立一个类,继承AbsRequest,我这里就建立一个TextRequest,访问百度翻译api的(在注释中有详细的讲解):
public class TextRequest extends AbsRequest<String> {
public RequestCallBack mCallBack;
public Map<String, String> mPostMap;
public Map<String, String> mHeadersMap;
private int method;
private static String url = "http://192.168.1.36:8080/volloryText/post.php";
//private static String url = "http://192.168.1.36:8080/volloryText/post.php";
private static String urls = "http://openapi.baidu.com/public/2.0/bmt/translate";
private static String BAIDUKEY = "xxxxxxxxxxxxx";
private static String src = "我不认识你的啊";
private static String parm;
//用于初始化的,可以根据自己的实际需要添加参数
/*觉得值得一提的就是,super中设置的super(0,url, callBack.mErrorCallBack);
* 第一个参数是网络访问方式get/post,第二个参数是地址的url
* 我曾经出现过的疑问就是如果我get方法需要再url中带参数,我是不是要在初始化实体的时候就把带参数的url建立好
* 如果是的话,那建立这个独立的类的意义就不大了,所以答案是否定的。
* 这里super只是设定一个默认值,到真正访问网络的时候,会优先使用重载函数getUrl()和getMethod()等的返回值。
* 所以我们只需要把值传入内部进行处理,在外只要一句话就能初始化实体。
*
*/
public TextRequest(int method,RequestCallBack callBack) {
super(0,url, callBack.mErrorCallBack);
// TODO Auto-generated constructor stub
this.method = method;
this.mCallBack = callBack;
this.setShouldCache(false);
}
public TextRequest(int method,String id,String name,String sex,RequestCallBack callBack) {
// super(url + "?" + parm, callBack.mSuccessCallBack, callBack.mErrorCallBack);
super(0,url, callBack.mErrorCallBack);
this.setShouldCache(false);
}
/*
* (non-Javadoc)
* @see com.example.textvolley.AbsRequest#parseNetworkResponse(com.android.volley.NetworkResponse)
* 这个类是处理返回的信息类型的,response中包含就所有访问网络后返回的数据,这里是用volley中的一个工具类HttpHeaderParser来定义返回数据的编码方式
* 因为volley在默认情况加是不支持中文的,所以如果在访问的http头信息中没有定义编码方式,他就会默认使用iso-8859-1
* 我们就需要HttpHeaderParser.parseCharset(response.headers, "UTF-8")来指定,不然有可能会出现中文乱码
*/
@Override
protected Response<String> parseNetworkResponse(NetworkResponse response) {
String parsed;
try {
parsed = new String(response.data, HttpHeaderParser.parseCharset(response.headers, "UTF-8"));
} catch (UnsupportedEncodingException e) {
parsed = new String(response.data);
}
return Response.success(parsed, HttpHeaderParser.parseCacheHeaders(response));
}
/*
* (non-Javadoc)
* @see com.example.textvolley.AbsRequest#getHeaders()
* 设置头信息
*/
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
// TODO Auto-generated method stub
if (mHeadersMap != null){
mHeadersMap.put("charset", "UTF-8");
return mHeadersMap;
}
else{
mHeadersMap = new HashMap<String, String>();
mHeadersMap.put("charset", "UTF-8");
return mHeadersMap;
}
}
/*
* (non-Javadoc)
* @see com.example.textvolley.AbsRequest#getMethod()
* 设置访问网络的方式get/post
*/
@Override
public int getMethod() {
// TODO Auto-generated method stub
return this.method;
}
/*
* (non-Javadoc)
* @see com.example.textvolley.AbsRequest#getUrl()
* 设置网络地址,在这里可以添加get参数
*/
@Override
public String getUrl() {
// TODO Auto-generated method stub
return urls + buildURL();
}
/*
* (non-Javadoc)
* @see com.example.textvolley.AbsRequest#getParams()
* 添加post的参数
*/
@Override
protected Map<String, String> getParams() throws AuthFailureError {
// TODO Auto-generated method stub
if (mPostMap != null){
return mPostMap;
}
else{
mPostMap = new HashMap<String, String>();
mPostMap.put("parm", "我不知道你说什么");
return mPostMap;
}
}
/*
* 生成get参数的url穿,指定使用utf-8
*/
public String buildURL(){
List<BasicNameValuePair> params = new LinkedList<BasicNameValuePair>();
params.add(new BasicNameValuePair("client_id", BAIDUKEY));
params.add(new BasicNameValuePair("q", src));
params.add(new BasicNameValuePair("from", "auto"));
params.add
(new BasicNameValuePair("to", "wyw"));
//对参数编码
String p = URLEncodedUtils.format(params, "UTF-8");
parm = "?" + p;
return parm;
}
/*
* (non-Javadoc)
* @see com.example.textvolley.AbsRequest#deliverResponse(java.lang.Object)
* 访问网络成功后,返回需要做的,一般是调用callback回调。
*/
@Override
protected void deliverResponse(String paramT) {
// TODO Auto-generated method stub
System.out.println(paramT);
mCallBack.mSuccessCallBack.onResponse(paramT);
}
}
这样在需要使用翻译api的地方
RequestCallBack callBack = new RequestCallBack() {
@Override
public void onResponse(String arg0) {
// TODO Auto-generated method stub
Log.d("string request success linstener", arg0 + "");
}
@Override
public void onErrorResponse(VolleyError arg0) {
// TODO Auto-generated method stub
Log.d("string request error linstener", arg0.getMessage() + "");
}
};
TextRequest baiduRequest = new TextRequest(Method.GET, callBack);
mRequestQueue.add(baiduRequest);
感觉这个activity的代码可读性会提高不少。
后记:
1,因为才开始尝试自己写,没什么经验,所以还是觉得写得不是很好,特别是callBack的抽象类。希望有更好 的建议
2,在官方的Request之类中也有很多不同类型的子类,例如jsonOBJ之类的,因为Request<T>是泛型,我们在 建立AbsRequest的子类时,也可以利用这一点,建立独特返回类型的子类。只要在重载 parseNetworkResponse时做不同的处理就可以了。
3,还是那句,刚刚起步,期待提高。