上一篇博客(http://1029457926.iteye.com/blog/2203653)详细的讲了Volley的原理及用法,在实际开发中可能并不那么实用,下面来总结我们项目中是如何封装使用的。
1 Volley是用来请求网络数据的,首先我们要准备好要传递的URL参数
HashMap params = new HashMap();
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 data, String tag, final CallbackLightRequest callback) {
if (!ConfigRequests.isNetworkOkWithAlert(mContext)) {
callNetworkError(tag, url, data, callback);
return;
}
Map 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 map) {
StringBuilder sb = new StringBuilder();
String value;
try {
if (map != null && map.size() > 0) {
for (Entry 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() {
@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 getHeaders() throws AuthFailureError {
/* 此处是相对于实际业务配置的 */
return new HashMap();
}
};
mQueue.add(req);
}
说明:Volley有2种回调一种是onResponse,一种是onErrorResponse,但是实际开发中可能需要更多的回调需要处理,例如:
1 请求服务器成功,数据无误
2 请求服务器成功,但是可能返回的JSON数据有问题
3 服务器请求成功,但是返回码有问题
4 无网络连接
5 网络正常,但是服务器没返给我们数据(刷新失败)
6 系统发生异常
......
当然我们可以根据实际业务需求来设定相应的回调。
上面我只做了一个CallBack来回调,不管请求失败还是成功,我都调用了onFinish()方法
4 回调处理
try {
request.get(url, params, "", new CallbackLightRequest() {
@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 {
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> httpCallback) {
HashMap params = new HashMap();
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 void doRequest(LightRequest request,
String url, HashMap params,
final HttpCallback callback, final Class> cls) {
try {
request.get(url, params, "", new CallbackLightRequest() {
@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>() {
@Override
public void onResponse(ApiBeans.FollowerListObject 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非常大的一个优点。