当前位置: 代码迷 >> Android >> android网络请求框架Volley(2)
  详细解决方案

android网络请求框架Volley(2)

热度:63   发布时间:2016-04-28 01:22:10.0
android网络请求框架Volley(二)

?? ?上一篇博客(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非常大的一个优点。
?
?
  相关解决方案