Android实习生 —— 网络请求及数据解析

96
博儿丶
0.1 2017.04.07 20:52* 字数 2669

目录

前言
    1、http协议定义
    2、客户端连接服务器实现内部的原理
    3、Http请求方式、区别
    4、HTTP返回请求数据的三种方式:
一、Android中的网络请求方式
    1、在Android上发送HTTP请求的方式
    2、关于HttpClient的废除
    3、HttpURLConnection、HttpCient介绍。(HttpCient废除之前)
    4、HttpURLConnection和HttpCient区别(HttpURLConnection优势)
    5、Android配置网络权限
二、HttpURLConnection(Demo)
    1、Get请求的实现(Demo)
    2、Post请求实现(Demo)
三、HttpCient(Demo)
    1、关于 HttpCient废除
    2、HttpCient介绍
    3、HttpCient实现步骤
    4、HttpCient实现实例(GET)(Demo)
    5、HttpCient实现实例(POST)(Demo)
四、HttpURLConnection抽象请求方法(Demo)
    1、JQuery
    2、定义接口HttpCallbackListener,为了实现回调
    3、创建HttpTool类,抽象请求方法(GET)
    4、调用示例
    5、抽象请求方法(POST)
五、文件下载(Demo)
    1、DownLoadManager简介
    2、功能实现
六、JSON数据解析(Demo)
    1、解析单条Json数据
    2、解析多条Json数据
七、图片数据解析(Demo)
【附录】
    Demo

前言

大部分andriod应用需要与服务器进行数据交互,HTTP、FTP、SMTP或者是直接基于SOCKET编程都可以进行数据交互,但是HTTP必然是使用最广泛的协议

在总结之前先来了解一下Http协议,也是对技术支持的一些补充。

1、http协议定义

HTTP协议是基于TCP/IP协议之上的协议,是客户端服务器之间的应用层的协议,是通用的、无状态的面向对象的协议。

2、客户端连接服务器实现内部的原理

分析上图,步骤如下:

  • 第一步:在浏览器客户端中得到用户输入的内容。

  • 第二步:浏览器得到这个网址之后,内部会将这个域名发送到DNS上,进行域名解析。得到它的IP之后就会链接到指定的服务器上,假如服务器的地址是:221.104.13.32:80,从浏览器到服务器端口它使用到最底层的TCP/IP协议。

  • 第三步:实现TCP/IP协议用Socket来完成,使用了Socket的套接字。

  • 第四步:服务器端的80端口监听客户端的链接,这样客户端到服务器就链接上了。

通俗一点讲,用户在浏览器输入网址,通过http协议发出去,网址经过DNS域名解析,解析成指定的ip地址,并在80端口上监听用户的请求。服务器监听到请求之后,会以三种方式返回给客户端:HTML、XML、JASON。

3、Http请求方式、区别

根据HTTP标准,HTTP请求可以使用多种请求方法。例如:HTTP1.1支持7种请求方法:GET、POST、HEAD、OPTIONS、PUT、DELETE和TARCE。在Internet应用中,最常用的方法是GET和POST。

区别:

  • 在客户端,GET方式在通过URL提交数据,数据在URL中可以看到;POST方式,数据放在HTML HEADER内提交。

  • 对于GET方式,服务器端用Request.QueryString获取变量的值,对于POST方式,服务器用Request.Form获取提交的数据。

  • GET方式提交的数据不能大于2KB(主要是URL长度限制),而POST则没有此限制。

  • 安全性问题。使用GET的时候,参数会显示在地址栏上,而POST不会。所以,如果这些数据是中文数据而且是非敏感数据,那么使用GET;如果用户输入的数据不是中文字符而且包含敏感数据,那么还是使用POST为好。

4、HTTP返回请求数据的三种方式:
  • 以HTML代码内容返回。
  • 以XML字符串的形式返回,在以后的android开发中这种形式返回数据比较多。
  • 以JSON对象形式返回,在网络流量上考虑JSON要比XML方式要好一些,便于解析。
    在Android当中,一般使用xml和Json数据解析。

一、Android中的网络请求方式

Android中的WebView控件已经在后台帮我们处理好了发送HTTP请求、接收服务响应、解析返回数据,以及最终的页面展示这几步工作,不过由于它封装得太好了,反而不能直观地看出HTTP协议是如何工作的。因此接下来我们通过手动发送HTTP请求的方式,来更加深入的了解这一过程。

1、在Android上发送HTTP请求的方式

一般有两种:HttpURLConnection、HttpCient

2、关于HttpClient的废除
  • 在android 6.0(api 23) SDK,不再提供org.apache.http.*(只保留几个类),HttpClient相关类移除,推荐使用HTTPURLConnection。
  • 废除原因:之前一直使用HttClient是由于HttpURLConnection不稳定导致,那么现在谷歌虽然修复了HttpURLConnection之前存在的一些问题。
  • 若还需使用该类,点击查看解决办法
3、HttpURLConnection、HttpCient介绍。(HttpCient废除之前)
  • HttpClient是apache的开源框架,封装了访问http的请求头,参数,内容体,响应等等,使用起来比较方便,而HttpURLConnection是java的标准类,什么都没封装,用起来太原始,不方便,比如重访问的自定义,以及一些高级功能等。

  • 从稳定性方面来说的话,HttpClient很稳定,功能强,BUG少,容易控制细节,而之前的HttpURLConnection一直存在着版本兼容的问题,不过在后续的版本中已经相继修复掉了。

4、HttpURLConnection和HttpCient区别(HttpURLConnection优势)
  • 1、HttpUrlConnection是Android SDK的标准实现,而HttpClient是apache的开源实现;

  • 2、HttpUrlConnection直接支持GZIP压缩;HttpClient也支持,但要自己写代码处理;

  • 3、HttpUrlConnection直接在系统层面做了缓存策略处理,加快重复请求的速度。

  • 4、HttpUrlConnection直接支持系统级连接池,即打开的连接不会直接关闭,在一段时间内所有程序可共用;HttpClient当然也能做到,但毕竟不如官方直接系统底层支持好;

5、Android配置网络权限

因为需要访问网络,需在AndroidManifest.xml中添加如下权限

<uses-permission android:name="android.permission.INTERNET" />

二、HttpURLConnection(Demo)

1、Get请求实现(Demo)

由于网络请求可能造成耗时操作(网络环境差的情况下)对ui线程的阻塞,我们开启子线程去操作网络请求。
【关于UI线程,请看《Android实习生 —— 异步处理之Handler》

private void connectWithHttpURLConnection() {
        new Thread( new Runnable() {
            @Override
            public void run() {
                Message msg =new Message();
                HttpURLConnection connection = null;
                try {
                    // 调用URL对象的openConnection方法获取HttpURLConnection的实例
                    URL url = new URL("http://www.baidu.com");
                    connection = (HttpURLConnection) url.openConnection();
                    // 设置请求方式,GET或POST
                    connection.setRequestMethod("GET");
                    // 设置连接超时、读取超时的时间,单位为毫秒(ms)
                    connection.setConnectTimeout(8000);
                    connection.setReadTimeout(8000);
                    // 设置是否使用缓存  默认是true
                    connection.setUseCaches(true);
                    //设置请求头里面的属性
                    //connection.setRequestProperty();
                    // 开始连接
                    Log.i("HttpURLConnection.GET","开始连接");
                    connection.connect();
                    if (connection.getResponseCode() == 200) {
                        Log.i("HttpURLConnection.GET", "请求成功");
                        InputStream in = connection.getInputStream();
                        // 使用BufferedReader对象读取返回的数据流
                        // 按行读取,存储在StringBuider对象response中
                        BufferedReader reader = new BufferedReader(new InputStreamReader(in));
                        StringBuilder response = new StringBuilder();
                        String line;
                        while ((line = reader.readLine()) != null) {
                            response.append(line);
                        }
                        // 此处省略处理数据的代码,通过handler直接将返回的结果消息发送给UI线程列队
                        Bundle bundle =new Bundle();
                        bundle.putString("data", String.valueOf(response));
                        msg.setData(bundle);
                        handler.sendMessage(msg);
                    }else{
                        Log.i("HttpURLConnection.GET", "请求失败");
                    }
                } catch (Exception e){
                    e.printStackTrace();
                } finally {
                    if (connection != null){
                        // 结束后,关闭连接
                        connection.disconnect();
                    }
                }
            }
        }).start();
    }
  • 效果


    Get请求效果
  • 打印消息


    打印消息
2、Post请求实现(Demo)

正如前言中第3条所述,在客户端,GET方式在通过URL提交数据,数据在URL中可以看到;POST方式,数据放在HTML HEADER内提交。

在Get方法中请求参数可以直接写到地址栏中,如:

//用“&”隔开不同参数
 String path = "https://reg.163.com/logins.jsp?id=helloworld&pwd=android";

但在Post方式中要把“请求的参数”转换为byte数组,然后通过DataOutputStream(urlConn.getOutputStream())把参数写入。

private void connectWithHttpURLConnectionPOST() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                Message msg = new Message();
                String path = "https://reg.163.com/logins.jsp";
                // 请求的参数转换为byte数组
                String params = null;
                HttpURLConnection urlConn = null;
                try {
                    params = "id=" + URLEncoder.encode("helloworld", "UTF-8")
                            + "&pwd=" + URLEncoder.encode("android", "UTF-8");

                    byte[] postData = params.getBytes();
                    // 新建一个URL对象
                    URL url = new URL(path);
                    // 打开一个HttpURLConnection连接
                    urlConn = (HttpURLConnection) url.openConnection();
                    // 设置连接超时时间
                    urlConn.setConnectTimeout(8 * 1000);
                    // Post请求必须设置允许输出
                    urlConn.setDoOutput(true);
                    // Post请求不能使用缓存
                    urlConn.setUseCaches(false);
                    // 设置为Post请求
                    urlConn.setRequestMethod("POST");
                    urlConn.setInstanceFollowRedirects(true);
                    // 配置请求Content-Type
                    urlConn.setRequestProperty("Content-Type",
                            "application/x-www-form-urlencode");
                    // 开始连接
                    urlConn.connect();
                    Log.i("HttpURLConnection.POST", "开始连接");
                    // 发送请求参数
                    DataOutputStream dos = new DataOutputStream(urlConn.getOutputStream());
                    dos.write(postData);
                    dos.flush();
                    dos.close();
                    // 判断请求是否成功
                    if (urlConn.getResponseCode() == 200) {
                        // 获取返回的数据
                        InputStream in = urlConn.getInputStream();
                        // 使用BufferedReader对象读取返回的数据流
                        // 按行读取,存储在StringBuider对象response中
                        BufferedReader reader = new BufferedReader(new InputStreamReader(in));
                        StringBuilder response = new StringBuilder();
                        String line;
                        while ((line = reader.readLine()) != null) {
                            response.append(line);
                        }
                        Log.i("HttpURLConnection.POST", "请求成功");
                        // 此处省略处理数据的代码,直接将返回的结果消息发送给UI线程列队
                        Bundle bundle = new Bundle();
                        bundle.putString("data", String.valueOf(response));
                        msg.setData(bundle);
                        handler.sendMessage(msg);
                    } else {
                        Log.i("HttpURLConnection.POST", "请求失败");
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    if (urlConn != null) {
                        // 结束后,关闭连接
                        urlConn.disconnect();
                    }
                }
            }
        }).start();
    }
  • 效果


    Post请求效果

三、HttpCient(Demo)

1、关于 HttpCient废除
  • 在android 6.0(api 23) SDK,不再提供org.apache.http.*(只保留几个类),HttpClient相关类移除,推荐使用HTTPURLConnection。
  • 废除原因:之前一直使用HttClient是由于HttpURLConnection不稳定导致,那么现在谷歌虽然修复了HttpURLConnection之前存在的一些问题。
  • 若还需使用该类,点击查看解决办法
2、HttpCient介绍

HttpClient其实是一个interface类型,HttpClient封装了对象需要执行的Http请求、身份验证、连接管理和其它特性。既然HttpClient是一个接口,因此无法创建它的实例。从文档上看,HttpClient有三个已知的实现类分别是:AbstractHttpClient, AndroidHttpClient, DefaultHttpClient,会发现有一个专门为Android应用准备的实现类AndroidHttpClient,当然使用常规的DefaultHttpClient也可以实现功能。

3、HttpCient实现步骤

(i)创建代表客户端的HttpClient对象。

(ii)创建代表请求的对象,如果需要发送GET请求,则创建HttpGet对象,如果需要发送POST请求,则创建HttpPost对象。
【对于发送请求的参数,GET和POST使用的方式不同,GET方式可以使用拼接字符串的方式,把参数拼接在URL结尾;POST方式需要使用setEntity(HttpEntity entity)方法来设置请求参数。】

(iii)调用HttpClient对象的execute(HttpUriRequest request)发送请求,执行该方法后,将获得服务器返回的HttpResponse对象。服务器发还给我们的数据就在这个HttpResponse相应当中。调用HttpResponse的对应方法获取服务器的响应头、响应内容等。

(iv)检查相应状态是否正常。服务器发给客户端的相应,有一个相应码:相应码为200,正常;相应码为404,客户端错误;相应码为505,服务器端错误。

(v)获得相应对象当中的数据。

4、HttpCient实现实例(GET)(Demo)
private void sendRequestWithHttpClient() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                //用HttpClient发送请求,分为五步
                //第一步:创建HttpClient对象
                HttpClient httpCient = new DefaultHttpClient();
                //第二步:创建代表请求的对象,参数是访问的服务器地址
                HttpGet httpGet = new HttpGet("http://www.baidu.com");
                try {
                    //第三步:执行请求,获取服务器发还的相应对象
                    HttpResponse httpResponse = httpCient.execute(httpGet);
                    //第四步:检查相应的状态是否正常:检查状态码的值是200表示正常
                    if (httpResponse.getStatusLine().getStatusCode() == 200) {
                        //第五步:从相应对象当中取出数据,放到entity当中
                        HttpEntity entity = httpResponse.getEntity();
                        String response = EntityUtils.toString(entity, "utf-8");//将entity当中的数据转换为字符串
                        //在子线程中将Message对象发出去
                        Message message = new Message();
                        message.what = SHOW_RESPONSE;
                        message.obj = response.toString();
                        handler.sendMessage(message);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
  • 效果


    Get请求效果
5、HttpCient实现实例(POST)(Demo)
private void sendRequestWithHttpClientPOST() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                //用HttpClient发送请求,分为五步
                //第一步:创建HttpClient对象
                HttpClient httpClient = new DefaultHttpClient();
                //第二步:创建代表请求的对象,参数是访问的服务器地址
                HttpPost httpPost= new HttpPost("https://reg.163.com/logins.jsp");
                // 使用NameValuePair(键值对)存放参数
                List<NameValuePair> data = new ArrayList<NameValuePair>();
                // 添加键值对
                data.add(new BasicNameValuePair("id", "helloworld"));
                data.add(new BasicNameValuePair("pwd", "android"));
                try {
                    // 使用setEntity方法传入编码后的参数
                    httpPost.setEntity(new UrlEncodedFormEntity(data, "utf-8"));
                    //第三步:执行请求,获取服务器发还的相应对象
                    HttpResponse httpResponse = httpClient.execute(httpPost);
                    //第四步:检查相应的状态是否正常:检查状态码的值是200表示正常
                    if (httpResponse.getStatusLine().getStatusCode() == 200) {
                        Log.i("mm","success");
                        //第五步:从相应对象当中取出数据,放到entity当中
                        HttpEntity entity = httpResponse.getEntity();
                        String response = EntityUtils.toString(entity, "utf-8");//将entity当中的数据转换为字符串
                        //在子线程中将Message对象发出去
                        Message message = new Message();
                        message.what = 1;
                        message.obj = response.toString();
                        handler.sendMessage(message);
                    }else{
                        Log.i("mm","fail");
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
  • 效果


    POST效果

四、HttpURLConnection抽象请求方法(Demo)

1、JQuery

如果你使用过JQuery(一个javasript库),你一定对JQuery的网路编程印象深刻,比如一个HTTP请求只需以下几行代码。

// JQuery的post方法
$.post("http://www.cnblogs.com/gzdaijie",{
        "stu_no":12345,
        "stu_name":"Tom",
    }).done(function(){
        //...请求成功的代码
    }).fail(function(){
        //...请求失败的代码
    }).always(function(){
        //...总会执行的代码
    })

我们当然不希望每次网络请求都写下“二”中那么繁琐的代码,那么android的HTTP请求能否像JQuery那么简单呢?当然可以!下面的代码实现了HttpURLConnection的HTTP请求方法封装

2、定义接口HttpCallbackListener,为了实现回调
// 定义HttpCallbackListener接口
// 包含两个方法,成功和失败的回调函数定义
public interface HttpCallbackListener {
    void onFinish(String response);
    void onError(Exception e);
}
3、创建HttpTool类,抽象请求方法(GET)
public class HttpTool {
    public static void sendRequest(final String address,
                                   final HttpCallbackListener listener) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                HttpURLConnection connection = null;
                try {
                    // 调用URL对象的openConnection方法获取HttpURLConnection的实例
                    URL url = new URL(address);
                    connection = (HttpURLConnection) url.openConnection();
                    // 设置请求方式,GET或POST
                    connection.setRequestMethod("GET");
                    // 设置连接超时、读取超时的时间,单位为毫秒(ms)
                    connection.setConnectTimeout(8000);
                    connection.setReadTimeout(8000);
                    // 设置是否使用缓存  默认是true
                    connection.setUseCaches(true);
                    //设置请求头里面的属性
                    //connection.setRequestProperty();
                    // 开始连接
                    Log.i("HttpURLConnection.GET","开始连接");
                    connection.connect();
                    if (connection.getResponseCode() == 200) {
                        Log.i("HttpURLConnection.GET", "请求chenggong");
                        InputStream in = connection.getInputStream();
                        BufferedReader reader = new BufferedReader(new InputStreamReader(in));
                        StringBuilder response = new StringBuilder();
                        String line;
                        while ((line = reader.readLine()) != null) {
                            response.append(line);
                        }
                        if (listener != null) {
                            // 回调方法 onFinish()
                            listener.onFinish(response.toString());
                        }
                    } else {
                        Log.i("HttpURLConnection.GET", "请求失败");
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    if (listener != null) {
                        // 回调方法 onError()
                        listener.onError(e);
                    }
                } finally {
                    if (connection != null) {
                        connection.disconnect();
                    }
                }
            }
        }).start();
    }
}
4、调用示例
button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //使用该HttpTool发起GET请求
                String url = "http://www.jianshu.com";
                HttpTool.sendRequest(url,new HttpCallbackListener(){
                    @Override
                    public void onFinish(String response) {
                        // ...省略对返回结果的处理代码
                        Message message = new Message();
                        message.what = 0;
                        message.obj = response.toString();
                        handler.sendMessage(message);
                    }

                    @Override
                    public void onError(Exception e) {
                        // ...省略请求失败的处理代码
                    }
                });

        }
        });
  • 效果


5、抽象请求方法(POST)
/* 在GET方法实现的基础上增加一个参数params即可,
 * 将参数转换为字符串后传入
 * 也可以传入键值对集合,再处理 */
public static void sendRequest(final String address,
    final String params, final HttpCallbackListener listener){
        //...
}

五、文件下载(Demo)

1、DownLoadManager简介

虽然我们可以通过HTTP请求的方式下载文件,在api level 9之后,android系统为我们提供了DownLoadManager类,这是android提供的系统服务,我们通过这个服务完成文件下载。整个下载过程全部交给系统负责,不需要我们过多的处理。
其包含两个内部类:

DownLoadManager.Query:主要用于查询下载信息。
DownLoadManager.Request:主要用于发起一个下载请求。
2、功能实现
 //使用系统下载器下载
    private void downloadAPK(String versionUrl, String versionName) {
        //创建下载任务
        DownloadManager.Request request = new DownloadManager.Request(Uri.parse(versionUrl));
        request.setAllowedOverRoaming(false);//漫游网络是否可以下载
        request.setTitle("jar包下载");//下载是通知栏标题
//        request.setAllowedNetworkTypes() 设置制定网络下下载,传入系统常量值。
//        提供的网络常量有:NETWORK_BLUETOOTH、NETWORK_MOBILE、NETWORK_WIFI。

        //设置文件类型,可以在下载结束后自动打开该文件
        MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton();
        String mimeString = mimeTypeMap.getMimeTypeFromExtension(MimeTypeMap.getFileExtensionFromUrl(versionUrl));
        request.setMimeType(mimeString);

        //在通知栏中显示,默认就是显示的
        request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE);
        request.setVisibleInDownloadsUi(true);

        //sdcard的目录下的download文件夹,必须设置
        request.setDestinationInExternalPublicDir("/download/", versionName);

        //request.setDestinationInExternalFilesDir(),也可以自己制定下载路径

        //将下载请求加入下载队列
        downloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);

        //加入下载队列后会给该任务返回一个long型的id,
        //通过该id可以取消任务,重启任务等等,看上面源码中框起来的方法
        mTaskId = downloadManager.enqueue(request);

        //注册广播接收者,监听下载状态
        registerReceiver(receiver,
                new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
    }

广播接收器

private BroadcastReceiver receiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            checkDownloadStatus();//检查下载状态
        }
    };

检查下载状态

private void checkDownloadStatus() {
        DownloadManager.Query query = new DownloadManager.Query();
        query.setFilterById(mTaskId);//筛选下载任务,传入任务ID,可变参数
        Cursor c = downloadManager.query(query);
        if (c.moveToFirst()) {
            int status = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS));
            switch (status) {
                case DownloadManager.STATUS_SUCCESSFUL:
                    Toast.makeText(this,"下载完成",Toast.LENGTH_SHORT).show();
                    break;
                case DownloadManager.STATUS_FAILED:
                    Toast.makeText(this,"下载失败",Toast.LENGTH_SHORT).show();
                    break;
            }
        }
    }
  • 效果


    下载效果
  • 文件下载路径


    文件下载路径

六、JSON数据解析(Demo)

1、解析单条Json数据
  • 单条数据
//单条数据
    private String parseItemJSONWithJSONObject(String jsonData) {
        String status=null;
        String message=null;
        try {
            //第一步:将从网络字符串jsonData字符串装入JSONObject
            JSONObject jsonObject = new JSONObject(jsonData);
            //第二步:因为单条数据,所以用jsonObject.getString方法直接取出对应键值
            status = jsonObject.getString("status");
            message = jsonObject.getString("message");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "status: "+ status+"\n"+"message: " + message;
    }
2、解析多条Json数据
  • 多条数据
//多条数据
    private String parseJSONWithJSONObject(String jsonData) {
        StringBuffer sb =new StringBuffer();
        try {
            //第一步:将从网络字符串jsonData字符串装入JSONObject,即JSONObject
            JSONObject jsonObject = new JSONObject(jsonData);
            //第二步:因为多条数据,所以将"取出来的、要遍历的"字段装入JSONArray(这里要遍历data字段)
            JSONArray jsonArray = jsonObject.getJSONArray("data");
            //第三步:循环遍历,依次取出JSONObject对象
            for (int i = 0; i < jsonArray.length(); i++) {
                JSONObject jsonObject2 = jsonArray.getJSONObject(i);
                String time = jsonObject2.getString("time");
                String ftime = jsonObject2.getString("ftime");
                String context = jsonObject2.getString("context");
                sb.append("time: " + time+"  "+"ftime: " + ftime+"\n"+"context: " + context+"\n\n");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return sb.toString();
    }
  • 效果


    单条

    多条

七、图片数据解析(Demo)

使用Http请求下载网络图片并通过handler机制更新系统ui。

public class MainActivity extends AppCompatActivity {
    private final String PATH = "https://www.baidu.com/img/bdlogo.png";
    private Button button;
    private ImageView imageView;
    public Handler handler = new Handler() {

        public void handleMessage(Message msg) {
            if (msg.what == RESULT_OK) {
                byte[] data = (byte[]) msg.obj;
                //使用Bitmap类解析图片
                Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0,
                        data.length);
                imageView.setImageBitmap(bitmap);
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        imageView = (ImageView) findViewById(R.id.imageView1);
        button = (Button) findViewById(R.id.btn);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                picDown();
            }
        });
    }

    private void picDown() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                HttpClient httpClient = new DefaultHttpClient();
                HttpGet httpGet = new HttpGet(PATH);
                try {
                    HttpResponse httpResponse = httpClient.execute(httpGet);
                    if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                        byte[] data = EntityUtils.toByteArray(httpResponse
                                .getEntity());
                        Message message = Message.obtain();
                        message.obj = data;
                        message.what = RESULT_OK;
                        handler.sendMessage(message);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    if (httpClient != null
                            && httpClient.getConnectionManager() != null) {
                        httpClient.getConnectionManager().shutdown();
                    }
                }
            }
        }).start();
    }

}

【附录】

Demo

整理作者:汪博
少壮不努力,老大徒悲伤。
本文为Android学习规划打造,如有不好的地方请多多指教。

Android复习
Web note ad 1