用Volley踩過的坑
相信volley絕大部分做android的人已經知道了,關于volley的使用網上也是一抓一大把,都是說volley如何如何好用,下面分享下自己在使用volley過程中踩過的坑。
volley好用的一個原因是封裝的api看起來也比較直接,但是其回調的api做的是一般般,其中有一個JsonObjectRequest類,網上的使用說明也一大把,基本上都是最簡單的情形:
Get請求示例:
RequestQueue queue = Volley.newRequestQueue(this);
String url = "http://m.weather.com.cn/data/101201401.html";
JsonObjectRequest objRequest = new JsonObjectRequest(url, null,
new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject obj) {
System.out.println("----------:" + obj);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
error.getMessage();
}
});
objRequest.setTag("obj");
queue.add(objRequest);Post請求示例:
Map<String,String> map=new HashMap<String,String>();
map.put("token", "AbCdEfGh123456");
JSONObject params=new JSONObject(map);
RequestQueue queue = Volley.newRequestQueue(this);
String url = "http://m.weather.com.cn/data/101201401.html";
JsonObjectRequest objRequest = new JsonObjectRequest(url, params,
new Response.Listener&lt;JSONObject&gt;() {
@Override
public void onResponse(JSONObject obj) {
System.out.println("----------:" + obj);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
error.getMessage();
}
});上面的兩個例子是使用的最簡單的情形,就是Get和Post請求都沒有帶上參數,于是百度這個問題得到的答案都是說通過 JsonObjectRequest的JsonObject jsonRequest這個參數來指定,官方的文檔對這個參數說的也是不清不楚的,這個地方看了半天也想不通參數為什么會是用json對象來傳遞,不應該是key=value的形式嗎?又多百度了幾遍,說是通過自定義JsonObjectRequest然后通過override其getParams函數來指定,但照做后這個函數不會被調用。。。百般無奈下只能看源碼了,看了源碼才發現JsonObjectRequest的構造函數里的 jsonRequest參數其實最終把JsonObject轉換成String,如果這個對象是空的,那么會默認以get請求(除非你指定是用 post),否則這個參數會當做是post的參數!看源碼:
//JsonRequest.java
@Override
public byte[] getBody() {
try {
return mRequestBody == null ? null : mRequestBody.getBytes(PROTOCOL_CHARSET);
} catch (UnsupportedEncodingException uee) {
VolleyLog.wtf("Unsupported Encoding while trying to get the bytes of %s using %s",
mRequestBody, PROTOCOL_CHARSET);
return null;
}
}具體getBody在哪里被調用就不具體來培析,有興趣的可自己研究源碼,看到這個,如果是說想繼承JsonOjectRequest又想用 key=value&key1=value1的形式來做參數的話肯定是想到了自定義的類里構造mRequestBody也就是 JsonObject轉換成String的地方用String(key=value形式)來代替用JsonObject來傳遞。于是做了如下修改:
String query = "";
if (mParams != null) {
Uri uri = Uri.parse(mUrl);
Uri.Builder builder = uri.buildUpon();
for (HashMap.Entry&lt;String, String&gt; entry : mParams.entrySet()) {
builder.appendQueryParameter(entry.getKey(), entry.getValue());
}
query = builder.build().getEncodedQuery();
} else {
}
mRequest = new MyJsonObjectRequest(mUrl, query, this, this);
//MyJsonObjectRequest.java 繼承JsonObjectRequest
public MyJsonObjectRequest(String url, String params, Response.Listener&lt;JSONObject&gt; listener, Response.ErrorListener errorListener) {
super(Method.POST, url, params, listener, errorListener);
}但最終還是不行!為什么? 參數傳遞沒有錯誤啊?事實上這里忘了一個非常重要的地方,也就是post請求的header,在發起key=value形式的參數時,我們請求的 Content-Type應該是application/x-www-form-urlencoded的,而JsonRequest默認是 application/json; charset=%s,這就是真相,于是重寫getBodyContentType
@Override
public String getBodyContentType() {
if (getMethod() == Method.POST) {
return "application/x-www-form-urlencoded";
}
return super.getBodyContentType();
}搞定了!
這里是不是還有人在想get請求如何傳參數的?用這種方式怎么get請求不能傳參,其實也是非常簡單,在請求時url就帶上key=value就好!如:
if (mParams != null) {
Uri uri = Uri.parse(url);
Uri.Builder builder = uri.buildUpon();
for (HashMap.Entry<String, String> entry : mParams.entrySet()) {
builder.appendQueryParameter(entry.getKey(), entry.getValue());
}
mUrl = builder.build().toString();
} else {
mUrl = url;
}聰明的你肯定想到了吧,希望給同樣用volley的同學有幫助~~
本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!