1、前言 前一段时间答应了师弟们写一个Android网络请求工具,由于项目的原因一直拖着。今天抽空写一个Demo演示一下,顺便复习一下Android的基本知识点。如有不足之处,请多多指点,谢谢(^_^)
2、HttpUrlConnection与HttpClient的区别 目前android实现网络请求有两种方式分别是HttpUrlConnection和HttpClient。 (1)HttpUrlConnection是java的核心类(这个类能在Android和java之间都能使用) HttpClient是Apache的开源项目,在Android之中已经默认集成此项目,在标准的java中不能直接使用(如果要使用需要引入Apache的项目包)
(2)HttpUrlConnection默认支持GZIP压缩,HttpClient默认不支持
根据官方指引Android版本2.2以后推荐使用HttpUrlConnection。嘿嘿!作为一名Android开发人员,官方的大腿还是得抱紧的啊(开玩笑>_<)
3、NetworkRequestTool的使用方法
按照惯例还是看一看项目结构,有两个java文件,不过重点是NetworkReuqestTool文件,我对HttpUrlConnection的基本操作做了封装,基本满足日常网络操作,需要使用的同学,直接将此文件Copy到自己的项目中即可。


Android网络编程Demo_第1张图片


(1)get请求的使用 先new一个实例,需要传入一个接口,必须重写三个方法,分别是networkSuccess,networkFailure,networkError。 其中networkSuccess方法传进来两个参数,resultString的访问指定地址成功之后返回的结果值,serverHeaderFieldBeanList (注意!这个值有可能为空,建议在使用之前判断是否为空)包含了服务器传回来的Cookies值和Headers值等等。
networkError方法,会传入一个errorString字符串。会大概告知错误的原因。
得到实例之后,调用getNetworkRequest传入一个网络地址(必传)和一个请求头参数(可以为空)。即可完成网络操作。
NetworkRequestTool networkRequestTool = new NetworkRequestTool(new NetworkRequestTool.NetworkCallbackListener() {    @Override    public void networkSuccess(String resultString, List<NetworkRequestTool.ServerHeaderFieldBean> serverHeaderFieldBeanList) {        for (int i = 0; i < serverHeaderFieldBeanList.size(); i++) {            NetworkRequestTool.ServerHeaderFieldBean serverHeaderFieldBean = serverHeaderFieldBeanList.get(i);            Log.e("----------->", serverHeaderFieldBean.getKey() + "   :  " + serverHeaderFieldBean.getValue());        }        txt.setText(resultString);        Log.e("----------->", resultString);    }    @Override    public void networkFailure() {        Log.e("----------->", "网络失败");    }    @Override    public void networkError(String errorString) {Toast.makeText(getApplication(), errorString, Toast.LENGTH_SHORT).show();    }});networkRequestTool.getNetworkRequest("http://www.baidu.com", null);


(2)post请求的使用 这个基本和上面的用法差不多,不过主要讲讲调用post请求的postNetworkRequest方法。 这个方法有两种类型,分别如下 第一种类型

public void postNetworkRequest(String urlString, HashMap<String, String> requestParamsMap, HashMap<String, String> jsonBody, HashMap<String, String> setRequestPropertyMap)
第二种类型
public void postNetworkRequest(String urlString, String requestParamsString, String jsonBody, HashMap<String, String> setRequestPropertyMap)
两种方法都是有四个参数需要传入 第一个,当然是指定的网络地址。 第二个,是(键值对&)格式的请求参数。 第三个,是json格式的键值对。 第四个,是设置请求头参数(一般可以不设置,传一个null)。
在第一种类型中,其实是将requestParamsMap,jsonBody做了进步一个的处理将其边为字符串,再调用第二种类型的方法。 例如:
HashMap<String, String> map = new HashMap<>();map.put("username", "C002563");map.put("password", "888");

传入给第一种类型的方法。里面的源码将会将这些键值对拼接成一个字符串username=C002563&password=888,再调用第二个方法,将其传入。 jsonBody也是如此,将这些键值对拼接成一个json格式{"username":"C002563","password":"888"},再调用第二个方法,将其传入。
HashMap<String, String> map = new HashMap<>();map.put("username", "C002563");map.put("password", "888");NetworkRequestTool networkRequestTool = new NetworkRequestTool(new NetworkRequestTool.NetworkCallbackListener() {    @Override    public void networkSuccess(String jsonString, List<NetworkRequestTool.ServerHeaderFieldBean> serverHeaderFieldBeanList) {        txt.setText(jsonString);        Log.e("----------->", jsonString);    }    @Override    public void networkFailure() {    }    @Override    public void networkError(String errorString) {    }});networkRequestTool.postNetworkRequest("网络地址", map, null, null);

当然你也可以这么写,不用HashMap了,咋们自己拼接了字符串,传进去


new NetworkRequestTool(new NetworkRequestTool.NetworkCallbackListener() {    @Override    public void networkSuccess(String jsonString, List<NetworkRequestTool.ServerHeaderFieldBean> serverHeaderFieldBeanList) {        txt.setText(jsonString);        Log.e("----------->", jsonString);    }    @Override    public void networkFailure() {    }    @Override    public void networkError(String errorString) {        Toast.makeText(getApplication(), errorString, Toast.LENGTH_SHORT).show();    }}).postNetworkRequest("网络地址", "username=C002563&password=888", null, null);

(3)post包含JSON格式的使用 这个例子的,我演示了一下请求头的设置以及服务器返回给我的Heardes和Cookies。 请求头和JSON格式,都是自己new一个HashMap,写入自己键值对。即可
主要讲讲serverHeaderFieldBeanList的使用。源码里面写了一个静态的实体类用来存放服务器返回的Headers和Cookies的键值对。 先判断是否为空(因为有些网络请求,服务器可能没有返回这些参数值。)由于ServerHeaderFieldBean实体类是在NetworkRequestTool里面,因此需要NetwrokRequestTool.ServerHeadersFieldBean。接着循环打印这些参数出来(你也可以根据需求实现自己的操作)。
//目标地址String url = "http://web.jingoal.com/module/common/Login.cjson?client=win&puse=win";//设置请求头参数HashMap<String, String> setRequestPropertyMap = new HashMap<>();//要求服务器返回JSON格式给我setRequestPropertyMap.put("Content-Type", "application/json; charset=utf-8");//设置请求json数据HashMap<String, String> jsonBodyMap = new HashMap<>();jsonBodyMap.put("login_name", "admin@3028216");jsonBodyMap.put("old_token", "");jsonBodyMap.put("pswd", "3dd635a808ddb6dd4b6731f7c409d53dd4b14df2");NetworkRequestTool networkRequestTool = new NetworkRequestTool(new NetworkRequestTool.NetworkCallbackListener() {    @Override    public void networkSuccess(String jsonString, List<NetworkRequestTool.ServerHeaderFieldBean> serverHeaderFieldBeanList) {        //判断是否为空        if (serverHeaderFieldBeanList != null) {            //获取服务器返回的Headers和Cookies            for (int i = 0; i < serverHeaderFieldBeanList.size(); i++) {                NetworkRequestTool.ServerHeaderFieldBean serverHeaderFieldBean = serverHeaderFieldBeanList.get(i);                Log.e("----------->我的测试", serverHeaderFieldBean.getKey() + "   :  " + serverHeaderFieldBean.getValue());            }        }        txt.setText(jsonString);        Log.e("----------->", jsonString);    }    @Override    public void networkFailure() {        Log.e("----------->", "网络失败");    }    @Override    public void networkError(String errorString) {        Log.e("----------->", "网络错误");    }    //在这里设置参数});networkRequestTool.postNetworkRequest(url, null, jsonBodyMap, setRequestPropertyMap);

至此,整个类的基本操作就结束了。
接下来看看Demo的效果图

4、NetworkRequestTool源码 这个类的源码,设计比较简单,不再多说了。
package sms.edward.per.myapplication;import android.os.Handler;import android.os.Message;import android.text.TextUtils;import android.util.Log;import java.io.BufferedInputStream;import java.io.ByteArrayOutputStream;import java.io.DataOutputStream;import java.io.IOException;import java.io.InputStream;import java.net.HttpURLConnection;import java.net.MalformedURLException;import java.net.URL;import java.util.ArrayList;import java.util.HashMap;import java.util.Iterator;import java.util.List;import java.util.Map;import java.util.Map.Entry;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;/** * description:网络请求工具 * * 此Demo博客地址:http://blog.csdn.net/u012814441/article/details/49643865 * <p/> * author:Edward * <p/> * 2015/10/26 */public class NetworkRequestTool {    private final String CONNECTION_NETWORK_FAILURE = "网络连接失败,请检查网络连接!";    private final String URL_PARSE_FAILURE = "URL解析错误";    private final String NETWORK_RESPONSE_FAILURE = "网络响应失败";    //连接时间,默认(5秒)    private int connTime = 5;    //读取时间,默认(5秒)    private int readTime = 5;    //返回数据成功    private int CONNECTION_SUCCEED = 200;    //编码类型,默认为UTF-8    private String encodingType = "utf-8";    //成功获取返回结果值    private final int GET_RESULT_STRING_SUCCEED = 1;    //获取返回结果值失败    private final int GET_RESULT_STRING_FAILURE = 0;    //网络错误    private final int ERROR = 2;    //回调监听接口    private NetworkCallbackListener networkCallbackListener;    //线程池变量    private ExecutorService executorService;    //是否开启线程池    private boolean isOpenThreadPool = true;    //线程变量    private Thread thread;    //    private List<ServerHeaderFieldBean> serverHeaderFieldList;    //设置编码格式    public void setEncodingType(String encodingType) {        this.encodingType = encodingType;    }    //设置连接时间    public void setConnTime(int connTime) {        if (connTime > 0) {            this.connTime = connTime;        } else {            Log.e("------------->", "设置连接时间不能少于0");        }    }    //设置读取时间    public void setReadTime(int readTime) {        if (readTime > 0) {            this.readTime = readTime;        } else {            Log.e("------------->", "设置读取时间不能少于0");        }    }    //设置回调接口    public void setNetworkCallbackListener(NetworkCallbackListener networkCallbackListener) {        this.networkCallbackListener = networkCallbackListener;    }    /**     * 构造方法     *     * @param networkCallbackListener     */    public NetworkRequestTool(NetworkCallbackListener networkCallbackListener) {        this(5, 5, 5, true, networkCallbackListener);    }    /**     * 构造方法     *     * @param connTime     * @param readTime     * @param threadPoolNumber     * @param isOpenThreadPool     * @param networkCallbackListener     */    public NetworkRequestTool(int connTime, int readTime, int threadPoolNumber, boolean isOpenThreadPool, NetworkCallbackListener networkCallbackListener) {        this.connTime = connTime;        this.readTime = readTime;        this.isOpenThreadPool = isOpenThreadPool;        this.networkCallbackListener = networkCallbackListener;        //初始化线程池(默认为5)        executorService = Executors.newFixedThreadPool(threadPoolNumber);    }    /**     * get网络请求(异步)没有包含设置请求头参数     */    public void getNetworkRequest(String url) {        getNetworkRequest(url, null);    }    /**     * get网络请求(异步)包含设置请求头参数     */    public void getNetworkRequest(String url, HashMap<String, String> setRequestPropertyMap) {        if (TextUtils.isEmpty(url)) {            Log.e("---------->", "url不能为空");            return;        }        //是否使用线程池        if (isOpenThreadPool) {            executorService.submit(new GetThreadRunnable(url, setRequestPropertyMap));        } else {            thread = new Thread(new GetThreadRunnable(url, setRequestPropertyMap));            //开启一个线程            thread.start();        }    }    /**     * post网络请求(异步)     *     * @param urlString             访问地址     * @param requestParamsMap      设置请求参数(字符串)     * @param jsonBody              设置josn格式参数(字符串)     * @param setRequestPropertyMap 设置请求头参数     */    public void postNetworkRequest(String urlString, HashMap<String, String> requestParamsMap, HashMap<String, String> jsonBody, HashMap<String, String> setRequestPropertyMap) {        if (TextUtils.isEmpty(urlString)) {            Log.e("---------->", "url不能为空");            return;        }        //将HashMap的requestParamsMap拼接成一个字符串        String resultRequestString = combineRequestParams(requestParamsMap);        //将HashMap的jsonBody拼接成一个字符串。        String resultJsonString = combineJsonBody(jsonBody);        //调用        postNetworkRequest(urlString, resultRequestString, resultJsonString, setRequestPropertyMap);    }    /**     * post网络请求(异步)     *     * @param urlString             访问地址     * @param requestParamsString   设置请求参数(HashMap)     * @param jsonBody              设置josn格式参数(HashMap)     * @param setRequestPropertyMap 设置请求头参数     */    public void postNetworkRequest(String urlString, String requestParamsString, String jsonBody, HashMap<String, String> setRequestPropertyMap) {        if (isOpenThreadPool) {            executorService.submit(new PostThreadRunnable(urlString, requestParamsString, jsonBody, setRequestPropertyMap));        } else {            thread = new Thread(new PostThreadRunnable(urlString, requestParamsString, jsonBody, setRequestPropertyMap));            //开启一个线程            thread.start();        }    }    /**     * GET的线程操作     */    public class GetThreadRunnable implements Runnable {        private String urlString;        private HashMap<String, String> setRequestPropertyMap;        public GetThreadRunnable(String urlString, HashMap<String, String> setRequestPropertyMap) {            this.urlString = urlString;            this.setRequestPropertyMap = setRequestPropertyMap;        }        @Override        public void run() {            try {                URL url = new URL(urlString);                HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();                // 忽略缓存                httpURLConnection.setUseCaches(false);                //设置读取时间                httpURLConnection.setReadTimeout(readTime * 1000);                //设置连接时间                httpURLConnection.setConnectTimeout(connTime * 1000);                //提出Post请求                httpURLConnection.setRequestMethod("GET");                //设置请求头参数(请求参数必须写在Http正文之内)                if (setRequestPropertyMap != null) {                    setRequestProperty(httpURLConnection, setRequestPropertyMap);                }                //获取服务器返回Header                getServerHeaderField(httpURLConnection);                int responseCode = httpURLConnection.getResponseCode();                if (responseCode == CONNECTION_SUCCEED) {                    //此处才是发送数据的真正操作                    InputStream inputStream = httpURLConnection.getInputStream();                    String responseResult = inputStreamConvertString(inputStream);                    if (!TextUtils.isEmpty(responseResult)) {//                        Log.e("----------->网络请求工具最终返回值", responseResult);                        handler.sendMessage(handler.obtainMessage(GET_RESULT_STRING_SUCCEED, responseResult));                    } else {                        handler.sendEmptyMessage(GET_RESULT_STRING_FAILURE);                    }                } else {                    handler.sendMessage(handler.obtainMessage(ERROR, NETWORK_RESPONSE_FAILURE));                }            } catch (MalformedURLException e) {                Log.e("--------------->", "Url字符串解析错误!");                handler.sendMessage(handler.obtainMessage(ERROR, URL_PARSE_FAILURE));            } catch (IOException e) {                Log.e("--------------->", "网络连接失败,请检查网络连接!");                handler.sendMessage(handler.obtainMessage(ERROR, CONNECTION_NETWORK_FAILURE));            }        }    }    /**     * 获取服务器返回的Header(不可覆盖)     *     * @param httpURLConnection     */    private void getServerHeaderField(HttpURLConnection httpURLConnection) {        //实例化        serverHeaderFieldList = new ArrayList<>();        String key = null;        for (int i = 1; (key = httpURLConnection.getHeaderFieldKey(i)) != null; i++) {            ServerHeaderFieldBean searverHeaderFieldBean = new ServerHeaderFieldBean();            searverHeaderFieldBean.setKey(key);            searverHeaderFieldBean.setValue(httpURLConnection.getHeaderField(key));            Log.e("----->服务器HeaderField", key + ":" + httpURLConnection.getHeaderField(key));            serverHeaderFieldList.add(searverHeaderFieldBean);        }    }    /**     * POST的线程操作     */    public class PostThreadRunnable implements Runnable {        private String urlString;        private String requestParamsString;        private String jsonBody;        private HashMap<String, String> setRequestPropertyMap;        public PostThreadRunnable(String urlString, String requestParamsString, String jsonBody, HashMap<String, String> setRequestPropertyMap) {            this.urlString = urlString;            this.jsonBody = jsonBody;            this.requestParamsString = requestParamsString;            this.setRequestPropertyMap = setRequestPropertyMap;        }        @Override        public void run() {            try {                URL url = new URL(urlString);                HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();                httpURLConnection.setDoOutput(true);                httpURLConnection.setDoInput(true);                // 忽略缓存                httpURLConnection.setUseCaches(false);                //设置读取时间                httpURLConnection.setReadTimeout(readTime * 1000);                //设置连接时间                httpURLConnection.setConnectTimeout(connTime * 1000);                //提出Post请求                httpURLConnection.setRequestMethod("POST");                //设置请求头参数(请求参数必须写在Http正文之内)                if (setRequestPropertyMap != null) {                    setRequestProperty(httpURLConnection, setRequestPropertyMap);                }                //开启一个输出流(getOutputStream方法已经在里面调用connect方法)                DataOutputStream dataOutputStream = new DataOutputStream(httpURLConnection.getOutputStream());                //设置请求参数                if (requestParamsString != null) {                    dataOutputStream.write(requestParamsString.getBytes(encodingType));                }                //设置实体JSON参数                if (jsonBody != null) {                    dataOutputStream.write(jsonBody.getBytes(encodingType));                    Log.e("------------>设置JSON:", jsonBody);                }                dataOutputStream.flush();                dataOutputStream.close();                //获取服务器返回Header                getServerHeaderField(httpURLConnection);                //得到网络响应码                int responseCode = httpURLConnection.getResponseCode();                if (responseCode == CONNECTION_SUCCEED) {                    //此处才是发送数据的真正操作                    InputStream inputStream = httpURLConnection.getInputStream();                    String responseResult = inputStreamConvertString(inputStream);                    if (!TextUtils.isEmpty(responseResult)) {//                        Log.e("----------->网络请求工具最终返回值", responseResult);                        handler.sendMessage(handler.obtainMessage(GET_RESULT_STRING_SUCCEED, responseResult));                    } else {                        handler.sendEmptyMessage(GET_RESULT_STRING_FAILURE);                    }                } else {                    handler.sendMessage(handler.obtainMessage(ERROR, NETWORK_RESPONSE_FAILURE));                }            } catch (MalformedURLException e) {                Log.e("--------------->", "Url字符串解析错误!");                handler.sendMessage(handler.obtainMessage(ERROR, URL_PARSE_FAILURE));            } catch (IOException e) {                Log.e("--------------->", "网络连接失败,请检查网络连接!");                handler.sendMessage(handler.obtainMessage(ERROR, CONNECTION_NETWORK_FAILURE));            }        }    }    /**     * 将输入流转换为字符串     *     * @param inputStream     * @return     * @throws IOException     */    public String inputStreamConvertString(InputStream inputStream) throws IOException {        if (inputStream == null) {            return null;        }        //将输入流暂时写进缓冲区中        BufferedInputStream bis = new BufferedInputStream(inputStream);        ByteArrayOutputStream bos = new ByteArrayOutputStream();        int length = 0;        byte[] by = new byte[1024];        while ((length = bis.read(by)) != -1) {            bos.write(by, 0, length);        }        bos.flush();        String result = new String(bos.toByteArray(), encodingType);        bos.close();        bis.close();        return result;    }    /**     * 拼接请求参数     *     * @return     */    public String combineRequestParams(HashMap<String, String> requestParamsMap) {        if (requestParamsMap == null) {            return null;        }        Iterator<Entry<String, String>> iterator = requestParamsMap.entrySet().iterator();        StringBuffer stringBuffer = new StringBuffer();        while (iterator.hasNext()) {            Map.Entry<String, String> tempMap = iterator.next();            stringBuffer.insert(0, tempMap.getKey() + "=" + tempMap.getValue() + "&");        }        //删除最后一个&        stringBuffer.deleteCharAt(stringBuffer.length() - 1);        System.out.println(stringBuffer.toString());        Log.e("-------------->拼接请求参数:", stringBuffer.toString());        return stringBuffer.toString();    }    /**     * 拼接字符串     *     * @param jsonBody     * @return     */    public String combineJsonBody(HashMap<String, String> jsonBody) {        if (jsonBody == null) {            return null;        }        Iterator<Entry<String, String>> iterator = jsonBody.entrySet().iterator();        StringBuffer stringBuffer = new StringBuffer();        stringBuffer.append("{");        while (iterator.hasNext()) {            Map.Entry<String, String> map = iterator.next();            // 将键值对插入到第1个字符之后(从0开始)            stringBuffer.insert(1, "\"" + map.getKey() + "\":\"" + map.getValue() + "\",");        }        //删除最后一个逗号        stringBuffer.deleteCharAt(stringBuffer.length() - 1);        stringBuffer.append("}");        Log.e("------------>拼接请求JSON参数", stringBuffer.toString());        return stringBuffer.toString();    }    /**     * 设置请求头参数(不能被覆盖)注意请求头参数的设置,因为它有可能决定了服务器返回值的类型     *     * @param httpURLConnection     */    private void setRequestProperty(HttpURLConnection httpURLConnection, HashMap<String, String> setRequestPropertyMap) {        Iterator<Entry<String, String>> iterator = setRequestPropertyMap.entrySet().iterator();        //设置遍历了一遍Map        while (iterator.hasNext()) {            Map.Entry<String, String> map = iterator.next();            Log.e("------------>设置请求头:", map.getKey() + "    " + map.getValue());            httpURLConnection.setRequestProperty(map.getKey(), map.getValue());        }    }    /**     * Handler处理子线程返回的数据     */    private Handler handler = new Handler() {        @Override        public void handleMessage(Message msg) {            //获取子线程发送过来的字符串            String resultString = (String) msg.obj;            switch (msg.what) {                case GET_RESULT_STRING_SUCCEED:                    //将子线程得到的结果值回调出去                    networkCallbackListener.networkSuccess(resultString, serverHeaderFieldList);                    break;                case GET_RESULT_STRING_FAILURE:                    networkCallbackListener.networkFailure();                    break;                case ERROR:                    networkCallbackListener.networkError(resultString);                    break;            }        }    };    /**     * 回调接口     */    public interface NetworkCallbackListener {        //网络连接成功        void networkSuccess(String returnString, List<ServerHeaderFieldBean> serverHeaderFieldBeanList);        //网络连接失败        void networkFailure();        //网络错误        void networkError(String errorString);    }    /**     * HeaderField实体类,用来保存服务器返回的Headers和Cookies     */    public static class ServerHeaderFieldBean {        private String key;        private String value;        public String getKey() {            return key;        }        public void setKey(String key) {            this.key = key;        }        public String getValue() {            return value;        }        public void setValue(String value) {            this.value = value;        }    }}

5、结束 谢谢各位。
源码请戳这里Android网络编程Demo




更多相关文章

  1. Android网络开发详解
  2. Android Studio - 第四十二期 几个经常用到的字符串的截取
  3. 360buy android 首页打开网络监控数据分析
  4. Android AdbCommandRejectedException和cannot bind to套接字地
  5. 字符串资源多国语言版本的出错问题
  6. Android 网络编程之---HttpClient 与 HttpURLConnection 共用coo
  7. android缓存框架ASimpleCache的使用 (网络请求数据并缓存)

随机推荐

  1. 理解MySQL——索引与优化总结
  2. Mysql 忘记root密码的完美解决方法
  3. 详解mysql 获取当前日期及格式化
  4. MariaDB 新版本实力逆袭不仅仅是 MySQL
  5. 详解MySQL中concat函数的用法(连接字符串)
  6. MySQL(win7x64 5.7.16版本)下载、安装、配
  7. 在Linux环境下mysql的root密码忘记解决方
  8. mysql批量更新多条记录的同一个字段为不
  9. 远程连接mysql错误代码1130的解决方法
  10. Windows下MySQL 5.7无法启动的解决方法