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
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Android进行网络请求可以使用OkHttp库。首先,创建一个空白的Java类,导入OkHttp相关的类和接口。然后,在类创建一个方法用于发送网络请求。这个方法内部使用OkHttp的`OkHttpClient`类创建一个实例,并使用`newCall()`方法创建一个`Call`对象来执行请求。接下来,使用`enqueue()`方法将请求加入到调度队列,并实现`Callback`接口来处理请求的成功和失败回调。在回调方法,可以通过`response`对象获取到请求返回的数据。为了确保在请求完成后能够获取到数据,可以使用一个循环卡住当前线程,直到数据返回成功。为了避免在主线程进行网络请求导致ANR错误,需要在子线程执行网络请求并等待数据返回成功后切换回主线程来刷新UI。可以使用`Thread`类创建一个新的子线程,并在其执行网络请求和UI刷新的操作。最后,启动子线程来执行网络请求的代码。 以下是一个示例代码来说明如何在Android进行网络请求: ``` new Thread(() -> { MyOkhttp myOkhttp = new MyOkhttp(); Request request = new Request.Builder() .url("网络地址") .build(); String data = myOkhttp.sendRequest(request); // 对获取到的数据进行解析和处理 // 注意:对UI进行更改需要切换为主线程,可以使用runOnUiThread()方法或Handler来切换主线程 }).start(); ``` 通过将网络请求的代码封装起来,可以避免重复编写相同的代码,提高效率。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值