上一篇博客(http://1029457926.iteye.com/blog/2203653)详细的讲了Volley的原理及用法,在实际开发中可能并不那么实用,下面来总结我们项目中是如何封装使用的。
1 Volley是用来请求网络数据的,首先我们要准备好要传递的URL参数
HashMap<String, String> params = new HashMap<String, String>(); params.put("user_id", userId); params.put("count", count + ""); params.put("since_time", timeSince); params.put("profile_user_id", profileUserId); String url = HttpConstant.DOMAIN_NORMAL + HttpConstant.FRIENDS_FANS_1;
2 把URL拼凑成一个完整的链接
public void get(String url, Map<String, String> data, String tag, final CallbackLightRequest<LightResponse> callback) { if (!ConfigRequests.isNetworkOkWithAlert(mContext)) { callNetworkError(tag, url, data, callback); return; } Map<String, String> defaultParams = ConfigRequests.getInstance().getDefaultParams(); if (defaultParams != null && defaultParams.size() > 0) { data.putAll(defaultParams); } if (data != null && data.size() > 0) { url = url + "?" + RequestUtils.map2QueryString(data); } this._get(url, tag, callback); }
拼凑URl的方法:map2QueryString
public class RequestUtils { /** * 生成QueryString,以 a=1&b=2形式返回 */ public static String map2QueryString(Map<String, String> map) { StringBuilder sb = new StringBuilder(); String value; try { if (map != null && map.size() > 0) { for (Entry<String, String> entry : map.entrySet()) { value = ""; value = entry.getValue(); if (StringUtils.isEmpty(value)) { value = ""; } else { value = URLEncoder.encode(value, Models.Encoding.UTF8); } sb.append(entry.getKey()).append("=").append(value) .append("&"); } sb.deleteCharAt(sb.length() - 1); } } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return sb.toString(); }
3 发送请求,并将请求放进Requestqueue中,我把请求统一封装在一个
AppRequest类中,这个类如下:
private void _get(final String url, final String tag, final Callback callback) { LogUtils.e(TAG, url); StringRequest req = new StringRequest(Request.Method.GET, url, new Listener<String>() { @Override public void onResponse(String text) { LogUtils.i(TAG, text); if (callback != null) { LightResponse res = new LightResponse(); res.tag = tag; res.url = url; res.status = Models.StatusCode.NetworkSuccess; res.setData(text); callback.onFinish(res); } } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { if (callback != null) { LightResponse res = new LightResponse(); res.tag = tag; res.url = url; res.status = Models.StatusCode.NetworkError; res.message = error.getMessage(); callback.onFinish(res); } } }) { @Override public Map<String, String> getHeaders() throws AuthFailureError { /* 此处是相对于实际业务配置的 */ return new HashMap<String, String>(); } }; mQueue.add(req); }
说明:Volley有2种回调一种是onResponse,一种是onErrorResponse,但是实际开发中可能需要更多的回调需要处理,例如:
1 请求服务器成功,数据无误
2 请求服务器成功,但是可能返回的JSON数据有问题
3 服务器请求成功,但是返回码有问题
4 无网络连接
5 网络正常,但是服务器没返给我们数据(刷新失败)
6 系统发生异常
......
当然我们可以根据实际业务需求来设定相应的回调。
上面我只做了一个CallBack来回调,不管请求失败还是成功,我都调用了onFinish()方法
4 回调处理
try { request.get(url, params, "", new CallbackLightRequest<LightResponse>() { @Override public void call(LightResponse response) { if (response.isReplied()) { ApiBeans.Followers2 bean = GsonUtil.getFromStr(ApiBeans.Followers2.class, response.getText());//json解析 if (bean != null && bean.data != null) { httpCallback.onResponse(bean.data);//请求成功 } else { httpCallback.onFailure(new RequestFailure(RequestFailure.Type.parse), null);//解析异常 } } else { httpCallback.onFailure(new RequestFailure(RequestFailure.Type.network), null);//网络异常 } } }); } catch (Exception ex) { httpCallback.onFailure(new RequestFailure(RequestFailure.Type.exception), ex);//异常处理 }
这里我做了2种类型的回调:
一 成功
二 失败(包含4种类型)
回调的接口如下:
public interface HttpCallback<T> { void onResponse(T response);//成功回调 void onFailure(RequestFailure failure, Exception ex);//异常处理 }错误的回调类型,这里当然也可以封装成一个泛型
public class RequestFailure { public enum Type { network,//网络问题 responseCode,//错误的返回码处理 exception,//系统异常 parse, //解析 } public RequestFailure(Type type) { this.what = type; } public Type what; }
network:代表网络连接异常
responseCode:错误的响应码处理
exception:系统异常处理
parse :Json解析异常
5 再次封装
当上面的代码写多了之后,你会发现你一直在写重复的代码,仔细看看除了回调的对象不一样之外,其它都参数都基本一样,很容易就想到用泛型来对上面的代码进行封装,代码如下:
public static void getFolowFansList(final Context context, final LightRequest request, String userId, String profileUserId, String timeSince, int count, final HttpCallback<ApiBeans.FollowerListObject<Fan>> httpCallback) { HashMap<String, String> params = new HashMap<String, String>(); params.put("user_id", userId); params.put("count", count + ""); params.put("since_time", timeSince); params.put("profile_user_id", profileUserId); String url = HttpConstant.DOMAIN_NORMAL + HttpConstant.FRIENDS_FANS_1; doRequest(request,url, data, httpCallback, ApiBeans.FollowerListObject.class); }把回调的代码用泛型进行封装
private static <T> void doRequest(LightRequest request, String url, HashMap<String, String> params, final HttpCallback callback, final Class<?> cls) { try { request.get(url, params, "", new CallbackLightRequest<LightResponse>() { @Override public void call(LightResponse response) { if (response.isReplied()) { T bean = GsonUtil.getFromStr(cls, response.getText()); if (bean != null) { callback.onResponse(bean); } else { callback.onFailure(new RequestFailure(RequestFailure.Type.parse), null); } } else { callback.onFailure(new RequestFailure(RequestFailure.Type.network), null); } } }); } catch (Exception ex) { callback.onFailure(new RequestFailure(RequestFailure.Type.exception), null); } }
6 volley 在项目中进行业务处理
下面看看如何现在封装的Volley在项目中进行业务处理的?
model.getFasList(mContext, lightRequest, Global.userDetail.userId, profileUserId, thisTimeSince, count, new HttpCallback<ApiBeans.FollowerListObject<Fan>>() { @Override public void onResponse(ApiBeans.FollowerListObject<Fan> data) { try { //数据返回成功 if (data.userList != null) { adapter.setIsAllLoaded(data.infoCount < Constant.FEED_DEFAULT_NUM); lv.setIfHasMore(data.infoCount, Constant.FEED_DEFAULT_NUM); if (isRefresh) { adapter.setDataList(data.userList); lv.setAdapter(adapter); } else { adapter.addDataList(data.userList); adapter.notifyDataSetChanged(); } } else { //刷新失败 if (isRefresh) { ToastModel.showRefreshFail(mContext); } else { ToastModel.showLoadMoreError(mContext); } } } catch (Exception e) { } finally { isDownloading = false; if (loadingView != null) { loadingView.setVisibility(View.GONE); loadingView = null; } refreshEnd(); } } @Override public void onFailure(RequestFailure failure, Exception ex) { //网络异常 if (failure.what == RequestFailure.Type.network) { ToastModel.showRed(mContext, R.string.tip_network_error); } else if (failure.what == RequestFailure.Type.parse) { //解析失败 ToastModel.showRed(mContext, "解析失败"); } else if (failure.what == RequestFailure.Type.exception) { //系统异常 ToastModel.showRed(mContext, "系统异常"); } } }); }
代码方便简单,通熟易懂,
层次分明,逻辑清晰有没有呢?
Volley不仅简化了我们的开发流程,而且可以让我们更专注于我们的业务处理。这是volley非常大的一个优点。