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,還是那句,剛剛起步,期待提高。