上一篇文章 [Volley+Gson]获取PM2.5小应用,我们介绍了使用Volley+Gson来获取并解析Json数据,我们使用的是JsonObjectRequest这个libs自带的方法,考虑到许多API都是使用Json数据,那我们何不把Gson一起打包到Request中,方便快捷!~那么我们接下来就来自定义一个可以获取+解析Json数据的Volley Requst
我们先找下参照物,上一篇文章我们使用的是JsonObjectRequest,而JsonObjectRequest是继承自抽象类 JsonRequest,JsonRequest定义如下:
public abstract class JsonRequest<T> extends Request<T> {
private static final String PROTOCOL_CHARSET = "utf-8";
private static final String PROTOCOL_CONTENT_TYPE = String.format("application/json; charset=%s", new Object[]{"utf-8"});
private final Listener<T> mListener;
private final String mRequestBody;
/** @deprecated */
public JsonRequest(String url, String requestBody, Listener<T> listener, ErrorListener errorListener) {
this(-1, url, requestBody, listener, errorListener);
}
public JsonRequest(int method, String url, String requestBody, Listener<T> listener, ErrorListener errorListener) {
super(method, url, errorListener);
this.mListener = listener;
this.mRequestBody = requestBody;
}
protected void deliverResponse(T response) {
this.mListener.onResponse(response);
}
protected abstract Response<T> parseNetworkResponse(NetworkResponse var1);
}
抽象方法 parseNetWorkResponse 在 JsonObjectRequest.class 定于:
protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
try {
String je = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
return Response.success(new JSONObject(je), HttpHeaderParser.parseCacheHeaders(response));
} catch (UnsupportedEncodingException var3) {
return Response.error(new ParseError(var3));
} catch (JSONException var4) {
return Response.error(new ParseError(var4));
}
}
需要注意两点1. JsonRequest 继承 Request 类,使用JsonRequest最终需要把参数通过supper传给父类,完成Http操作
2. 主要功能在于deliverResponse()以及parseNetworkResponse()这两个方法的实现,deliverResponse()调用了mListener中的onResponse()方法,并将response内容传入,以完成OnResponse的回调。parseNetworkResponse()则对服务器响应的数据进行解析,也就是我们今天使用Gson对Json数据进行解析的关键
public class GsonRequest<T> extends Request<T> {
private final Response.Listener<T> mListener;
private Gson mGson = new Gson();
private Class<T> mClass;
private Map<String,String> mHeaders;
// supprot Method and header modication
public GsonRequest(int method, String url,Response.Listener<T> mListener,
Response.ErrorListener errorlistener, Map<String, String> mHeaders, Class<T> mClass) {
super(method, url, errorlistener);
this.mListener = mListener;
this.mHeaders = mHeaders;
this.mClass = mClass;
}
// do not modfiy the header
public GsonRequest(int method, String url, Response.Listener<T> mListener,
Response.ErrorListener errorlistener,Class<T> mClass) {
super(method, url, errorlistener);
this.mListener = mListener;
this.mHeaders = null;
this.mClass = mClass;
}
// Get Method and Support header modication
public GsonRequest(String url,Response.Listener<T> mListener,
Response.ErrorListener errorlistener, Map<String, String> mHeaders, Class<T> mClass) {
super(Method.GET, url, errorlistener);
this.mListener = mListener;
this.mHeaders = mHeaders;
this.mClass = mClass;
}
//Get Method and Do not modify the header
public GsonRequest(String url, Response.Listener<T> mListener,
Response.ErrorListener errorlistener,Class<T> mClass) {
super(Method.GET, url, errorlistener);
this.mListener = mListener;
this.mHeaders = null;
this.mClass = mClass;
}
@Override
protected Response<T> parseNetworkResponse(NetworkResponse networkResponse) {
try {
String jsonString = new String(networkResponse.data,
HttpHeaderParser.parseCharset(networkResponse.headers));
return Response.success(mGson.fromJson(jsonString, mClass),
HttpHeaderParser.parseCacheHeaders(networkResponse));
} catch (UnsupportedEncodingException e) {
return Response.error(new ParseError(e));
}
}
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
return mHeaders == null? super.getHeaders():mHeaders;
}
@Override
protected void deliverResponse(T response) {
mListener.onResponse(response);
}
}
这里我比较贪心,把Header的信息也一起封装进去,所以就有 有/无Header 是/否Get方法 四种GsonRequest 方法
AqiInfo的定义和上一篇文章一样,不重复贴了
MainActivity的处理,如下
void GetPM25Value(String mCityName) {
String url = httpUrl + "?" + httpArg + mCityName; //make the url
GsonRequest<AqiInfo> request = new GsonRequest<AqiInfo>(url,new Response.Listener<AqiInfo>() {
@Override
public void onResponse(AqiInfo aqiInfo) {
if (aqiInfo.retData != null){
String mTime = aqiInfo.retData.time.substring(11,19);
mTv.setText(aqiInfo.retData.toString()+"time : "+ mTime + ",Today ");
} else {
mTv.setText("Can not Get Any Data From the Server");
}
}
} ,new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
if(error.toString().contains("UnknownHostException")) {
mTv.setText("Plz Connect the NetWork and Try Again ^.^");
} else {
mTv.setText("Sorry , Do not support this City T.T");
}
}
},mheader,AqiInfo.class);
mQueue.add(request);
}
其中,传入的参数 mheader 定义:
Map<String,String> mheader;
mheader = new HashMap<>();
mheader.put("apikey","您的用户apkapi");
将用户apikey传入,界面和上次一样,不贴咯~
然后发生了个 Warning
Signals places wherer an unchecked warning is issued by the compiler
很头疼,连英文都看不懂=。=,最后在Stack OverFlow找到答案 :
传送门
原来是我在引用GsonRequest的时候没初始化好
错误:
GsonRequest<AqiInfo> request = new GsonRequest(url,new Response.Listener<AqiInfo>()...
正确
GsonRequest<AqiInfo> request = new GsonRequest<AqiInfo>(url,new Response.Listener<AqiInfo>()...
类型不匹配导致的错误,参数一多,眼就花了 @。@
参考文章