Android网络请求中的回调

需求:高效地向服务器请求数据并解析。

涉及的主要工具类:
HttpManager 大哥类。最重要的类,封装了GET和POST方法。所有的参数都要经过这个类发送给服务器。
HttpRequestListener 监听接口。封装了请求状态和毁掉方法
HttpRequestVo 信使类。封装了http请求的参数。
JSONParser 解析器。

HttpRequestVo 封装了Http请求中携带的参数。这个类类似于一个通信使者,在主调用函数中赋值,传递给HttpManager,让后者将它进一步加工成http请求。

public class HttpRequestVo {

    //请求地址
    public String requestUrl;
    //上下文
    public Context context;
    //客户端的本地请求参数
    public HashMap<String, String> requestDataMap;
    //JSON请求参数
    public JSONObject requestJson;
    //JSON解析器
    public JSONParser parser;
}

HttpRequestListener是一个接口,它里面封装了几个Request的返回状态,还有一个很重要的回调方法action,用于返回网络请求的结果状态,以及解析好的数据Object(一般为HashMap)。

public interface HttpRequestListener {

    public static final int BASE_EVENT = 0x100;

    //没有网络提示
    public static final int EVENT_NO_NETWORK = BASE_EVENT + 1;
    //网络异常
    public static final int EVENT_NETWORK_ERROR = BASE_EVENT + 2;
    //获取网络数据失败
    public static final int EVENT_GET_DATA_ERROR = BASE_EVENT + 3;
    //获取网络数据成功
    public static final int EVENT_GET_DATA_SUCCESS = BASE_EVENT + 4;

    /**
     * 实现方法
     *
     * @param actionCode 事件代码
     * @param object 解析好并返回给调用者的最终数据
     */
    public abstract void action(int actionCode, Object object);

}

JSONParser的代码如下,它的作用将返回的网络数据由JSONObject格式解析为Bean。这里用到Gson来解析数据,这样的好处是:只用写一份代码,就可以解析任何类型的JSON数据,比如:得到news就解析成NewsBean,得到user就解析成UserBean。而Parser解析器只有一份,极大提高了代码的复用性。

public HashMap<String, Object> parseJSON(String paramString) throws JSONException {
    HashMap<String, Object> map = new HashMap<String, Object>();
    JSONObject jsonObject = new JSONObject(paramString);
    String result = jsonObject.getString("result");
     Gson gson = new Gson();
 map.put("datamap", gson.fromJson(result, cls));
    return map;

JavaBean的格式如下,存放的是一个列表,其中的元素是一个一个的Model。使用Gson,可以轻易地将返回数据中对应的字段解析为Bean中的成员。要注意:返回数据中的字段名应该与Bean中的变量名完全一致,否则无法解析成功。

public class NewsListEntity {

    public ArrayList<NewsModel> newsList;

    public static class NewsModel {
        public int news_id;             
        public int news_type;          
        public String news_title;   
        public String news_sub;        
        public String news_content;   
        public String news_imgurl; 
        public int istop;
        public String news_time;                   

    }
}

———主调用函数的使用———
代码如下。展示了主要流程:1.封装请求参数 2. 调用请求函数获取回调数据

protected void getNewsData(int type) {
        HttpRequestVo vo = new HttpRequestVo();
        vo.requestUrl = ConstantValues.GET_NEWS_LIST;
        vo.context = mContext;
        HashMap<String, String> map = new HashMap<String, String>();
        map.put("istop", "0");
        map.put("type", type + "");
        vo.requestDataMap = map;
        JSONObject requestJson = new JSONObject();  //目前暂时没用
        vo.parser = new JSONParser(NewsListEntity.class);
        vo.requestJson = requestJson;

        getDataFromServer(HttpManager.GET_METHOD, vo, new DataCallback<HashMap<String, Object>>() {
            @Override
            public void onStart() {

            }

            @Override
            public void onFailed() {

            }

            /**
             * 处理返回的news列表数据
             * @param paramObject
             */
            @Override
            public void processData(HashMap<String, Object> paramObject) {

                NewsListEntity newsEntity = (NewsListEntity) paramObject.get("datamap");

                ArrayList<NewsListEntity.NewsModel> newsList = newsEntity.newsList;

                mList.addAll(newsList);

                if (mListView.getAdapter() == null) {
                    mAdapter = new NewsItemAdapter(getContext(), mList);
                    mListView.setAdapter(mAdapter);
                } else {
                    mAdapter.notifyDataSetChanged();
                }
            }

            @Override
            public void onFinish() {
            }

        });

    }

下面这个就是回调接口。调用方(一般为Activity或Fragment)使用某个请求函数来向服务器请求数据时,要把该接口作为传入参数。

public abstract interface DataCallback<T> {
        public abstract void onStart();

        public abstract void onFailed();

        /**
         * 处理服务器返回的数据
         *
         * @param paramObject 服务器返回的数据实体
         */
        public abstract void processData(T paramObject);

        public abstract void onFinish();
    }

下面的代码展示将回调接口应用在主调用函数中。getDataFromServer这个主调用函数有三个参数,第一个你可以选择GET或POST,第二个是你自己定义的HttpRequestVo请求体,第三个就是上面提到的回调函数,在主调用函数中实现它里面的方法,对返回并解析好的数据进行使用。

/**
     * 从服务器上获取数据,并回调处理
     *
     * @param requestType
     * @param requestVo
     */
    protected void getDataFromServer(int requestType, HttpRequestVo requestVo, DataCallback callback) {
        final BaseHandler handler = new BaseHandler(mContext, callback);
        httpManager = new HttpManager(mContext, new HttpRequestListener() {
            @Override
            public void action(int actionCode, Object object) {
                Message msg = Message.obtain();
                switch (actionCode) {
                    case HttpRequestListener.EVENT_NO_NETWORK:
                        msg.what = HttpRequestListener.EVENT_NO_NETWORK;
                        break;
                    case HttpRequestListener.EVENT_NETWORK_ERROR:
                        msg.what = HttpRequestListener.EVENT_NETWORK_ERROR;
                        break;
                    case HttpRequestListener.EVENT_GET_DATA_ERROR:
                        msg.what = HttpRequestListener.EVENT_GET_DATA_ERROR;
                        msg.obj = null;
                        break;
                    case HttpRequestListener.EVENT_GET_DATA_SUCCESS:
                        msg.obj = object;
                        msg.what = HttpRequestListener.EVENT_GET_DATA_SUCCESS;
                        break;
                    default:
                        break;
                }
                handler.sendMessage(msg);
            }
        }, requestVo);
        callback.onStart();
        if (requestType == HttpManager.GET_METHOD) {
            /**
             *
             */
            httpManager.sendGetRequest();
        } else if (requestType == HttpManager.POST_METHOD) {
            /**
             *
             */
            httpManager.sendPostRequest();
        }
    }

下面以GET方法为例,看一下我们是如何发送Http请求的。前面的部分是遍历HttpRequestVo中的参数map,进行url的字符串拼接。拼接完成后,这里我们使用Volley来发送GET请求,这样可以避免书写繁琐的HttpUrlConnection、输入输出流语句,并且不需要另开一个线程,因为多线程代码已经被封装。如果请求成功,在回调函数的onsuccess方法中,需要做两件事:使用parser将请求到的JSONObject解析为Java对象;HttpRequestListener调用action回调方法,将解析结果传回给主调用函数getDataFromServer。

public void sendGetRequest() {
        requestStatus = 1;
        String urlStr = "";
        try {
            StringBuffer buffer = new StringBuffer();
            buffer.append(requestVo.requestUrl);
            if (requestVo.requestDataMap != null) {
                if (!buffer.toString().contains("?")) {
                    buffer.append("?");
                } else {
                    buffer.append("&");
                }
                HashMap<String, String> map = requestVo.requestDataMap;
                int i = 1;
                int size = map.size();
                for (Map.Entry<String, String> entry : map.entrySet()) {
                    if (i == size) {
                        if (TextUtils.isEmpty(entry.getValue())) {
                            buffer.append(entry.getKey() + "=");
                        } else {
                            buffer.append(entry.getKey() + "=" + requestEncodeStr(entry.getValue()));
                        }
                    } else {
                        if (TextUtils.isEmpty(entry.getValue())) {
                            buffer.append(entry.getKey() + "=" + "&");
                        } else {
                            buffer.append(entry.getKey() + "=" + requestEncodeStr(entry.getValue()) + "&");
                        }
                    }
                    i++;
                }
            }

            urlStr = buffer.toString();
            VolleyRequest.RequestGet(context, urlStr, "volleyGet",
                    new VolleyInterface(context, VolleyInterface.mListener, VolleyInterface.mErrorListener) {
                        @Override
                        public void onMySuccess(JSONObject result) {
                            if (result != null) {
                                try {
                                    if (requestVo.parser != null) {
                                        HashMap<String, Object> map = requestVo.parser.parseJSON(result.toString());
                                        listener.action(HttpRequestListener.EVENT_GET_DATA_SUCCESS, map);
                                    } else {
                                        listener.action(HttpRequestListener.EVENT_GET_DATA_SUCCESS, result);
                                    }

                                } catch (JSONException e) {
                                    e.printStackTrace();
                                }

                            }

                        }

                        @Override
                        public void onMyError(VolleyError error) {
                            listener.action(HttpRequestListener.EVENT_NETWORK_ERROR, null);
                            Log.i("TAG", error.toString());
                        }
                    });

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }

至此,我们已经获取到了封装好的JavaBean,剩下要做的就是把数据展现在UI上了。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值