Android之Http网络编程(四)

前面几篇博文简单的介绍了一些常见的Http的操作,这些操作几乎都是在新开的线程中进行的网络请求,并在日志中打印出获取到的网络数据。那么,问题来了!(呃~感觉下一句是蓝翔有木有?)如何在把获取到的网络数据显示在UI界面上呢?如果按照前几篇博文的例子,并在主线程中直接对子线程获取的网络数据直接进行操作就会发现一个问题,那就是在主线程中根本就获取不到子线程得到的从服务器返回的数据。因为,网络操作属于耗时操作,为了不阻塞主线程而放在子线程中,当主线程中的代码执行完后子线程未必就获取到服务器返回的数据了。所以,为了解决这样的问题我们通常在Http的操作中加上异步消息机制,并且为了简化操作对其进行简单的封装,加上回调机制。

这篇博文就以HttpClient访问百度首页为例子,对之前博文中的Http操作进一步的完善。

首先,先回忆一下使用HttpClient的最简单的步骤或者说是过程:

(这里的strurl为"http://www.baidu.com",str为从服务器返回的数据。)

HttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet(strurl);
HttpResponse response= client.execute(request);
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
String str = EntityUtils.toString(response.getEntity());
}

下面将基于上面的这些操作来实现简易封装:

首先加入回调机制:

(如果对回调还不太熟悉,请参考博文《java回调机制解析》)

public interface HttpCallback {

    void onSuccess(Object result);

    void onFailure(Exception result);

}

接下来,实现一个Request类:

这个类一共有三个属性:

method是在该类中用enum类型限定的RequestMethod类型的对象,用于设置请求方式。

url就是网络请求的路径。

callback为回调接口对象,用于在网络请求中获取到数据后将数据传递至调用处。

public class Request {
    public RequestMethod method;
    public String url;
    public HttpCallback callback;

    public Request(String url, RequestMethod method) {
        this.method = method;
        this.url = url;

    }

    public Request(String url) {
        this.method = RequestMethod.GET;
        this.url = url;

    }

    public enum RequestMethod {
        GET, POST, DELETE, PUT
    }

    public void setCallBack(HttpCallback callback) {
        this.callback = callback;
    }

    public void execute() {
        RequstTask task = new RequstTask(this);
        task.execute();

    }

}

从上面的代码可以看出,该类的两个构造函数,都需要传入URL,其中一个构造函数可以设置请求方式,另一个设置默认请求方式GET。
在该类中有一个execute()方法,在这个方法中RequestTask类继承于AsyncTask,它的作用就是在RequestTask中进行网络请求。

RequestTask代码如下:

public class RequstTask extends AsyncTask<Void, integer, Object> {
    private Request requset;

    public RequstTask(Request requset) {
        this.requset = requset;
    }

    @Override
    protected void onPreExecute() {
        // TODO Auto-generated method stub
        super.onPreExecute();
    }

    @Override
    protected Object doInBackground(Void... params) {
        try {
            HttpResponse response = HttpClientUtils.execute(requset);
            if (requset.callback != null) {
                //如果进一步抽象化回调接口,使其子抽象类能分别处理多种格式的数据(如:JSON、XML、String、File),可以更方便
                //这里直接使用返回String类型的数据
                if(response.getStatusLine().getStatusCode()==HttpStatus.SC_OK){
                    return EntityUtils.toString(response.getEntity());
                }
                return "请求失败";
            } else {
                return null;
            }

        } catch (Exception e) {
            return e;
        }
    }

    @Override
    protected void onPostExecute(Object result) {
        if (requset.callback != null) {
            if (result instanceof Exception) {
                requset.callback.onFailure((Exception) result);
            } else {
                requset.callback.onSuccess(result);
            }
        }

    }

    @Override
    protected void onProgressUpdate(integer... values) {
        // TODO Auto-generated method stub
        super.onProgressUpdate(values);
    }

}

这个类的构造函数需要传递一个Request对象,会根据这个Request对象的method属性确定请求方式、url属性确定请求路径,根据callback属性的有无来判断是否是否将获取到的网络数据传递至调用接口处。
在doInBackground()中如果Request对象的callback属性为null则返回null:

当Request对象的callback属性不为null,则先取出服务器返回的状态码(这里的response为服务器返回的信息),如果等于200(也就是HttpStatus.SC_OK)那么就说明响应成功了。再调用getEntity()方法获取到一个HttpEntity实例,然后再用EntityUtils.toString()这个静态方法将HttpEntity转换成字符串并return。返回后的数据将传入onPostExecute()方法中作为参数。

      if (requset.callback != null) {
                //如果进一步抽象化回调接口,使其子抽象类能分别处理多种格式的数据(如:JSON、XML、String、File),可以更方便
                //这里直接使用返回String类型的数据
                if(response.getStatusLine().getStatusCode()==HttpStatus.SC_OK){
                    return EntityUtils.toString(response.getEntity());
                }
                return "请求失败";
            } else {
                return null;
            }

在onPostExecute()中Request对象的callback属性为null根本就没返回。反之,doInBackground()的结果result将会传递至回调接口的调用处:

    if (requset.callback != null) {
            if (result instanceof Exception) {
                requset.callback.onFailure((Exception) result);
            } else {
                requset.callback.onSuccess(result);
            }
        }

在doInBackground()中有一句代码:

HttpResponse response = HttpClientUtils.execute(requset);

这里的HttpClientUtils其实就是一个简单的封装,其代码如下:

public class HttpClientUtils {

    public static HttpResponse execute(Request requst) throws Exception {
        switch (requst.method) {
        case GET:
            return get(requst);

        }
        return null;
    }

    private static HttpResponse get(Request requst)
            throws ClientProtocolException, IOException {
        HttpClient client = new DefaultHttpClient();
        HttpGet get = new HttpGet(requst.url);
        HttpResponse response = client.execute(get);
        return response;
    }

}

从代码中可以看出,execute()和get()方法都是static类型并且返回类型都是HttpResponse。在execute()方法中根据传入的Request对象的method属性结合switch语句执行相对应的网络请求方式,并返回从服务器获得HttpResponse类型的信息。这个信息在RequstTask类中被直接赋值使用。

大体的过程就是这样了。

最后的最后,在Activity中的使用:

public class MainActivity extends Activity {

    private Button btn;
    private TextView tv;
    private Request request;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        btn = (Button) findViewById(R.id.btn);
        tv = (TextView) findViewById(R.id.tv);
        request = new Request("http://www.baidu.com", RequestMethod.GET);
        btn.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                try {
                    request.setCallBack(new HttpCallback() {

                        @Override
                        public void onSuccess(Object result) {
                            tv.setText((String) result);
                        }

                        @Override
                        public void onFailure(Exception result) {
                            tv.setText("请求失败");

                        }

                    });
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                request.execute();
            }
        });
    }

}

Activity的布局文件如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <Button
        android:id="@+id/btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="请求" />

    <ScrollView
        android:id="@+id/sv"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <TextView
            android:id="@+id/tv"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent" />
    </ScrollView>

</LinearLayout>

运行程序,效果如下:

Demo下载:http://download.csdn.net/detail/af74776/8066779

时间: 2024-08-22 13:59:33

Android之Http网络编程(四)的相关文章

Android系列之网络(四)----SAX方式解析XML数据

?[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4044170.html 联系方式:[email protected] [系列]Android系列之网络:(持续更新) Android系列之网络(一)----使用HttpClient发送HTTP请求(通过get方法获取数据) Android系列之网络(二)----HTTP请求头与响应头 Androi

Android之Http网络编程(一)

Android应用作为一个客户端程序绝大部分都是需要进行网络请求和访问的,而http通信是一种比较常见并常用的通信方式. 在Android中http网络编程中有两种实现方式,一种是使用HttpURLConnection,另一种就是使用HttpClient. 这两种实现方式的大体过程都是: Android客户端向服务器发出请求. 服务端接收请求并响应. 服务端返回数据给客户端. 在Http通信中有POST和GET两种方式,其不同之处在于GET方式可以获得静态页面,同时可以将请求参数放在URL字符串

Android之Http网络编程(三)

在前面两篇博客<Android之Http网络编程(一)>.<Android之Http网络编程(二)>中,简单的介绍了对网页的请求和客户端与服务端的简单的参数交互.那么,这一篇博客就来认识一下Android客户端获取服务端返回的数据. 大家都知道客户端与服务端的交互大体过程如下: Android客户端向服务器发出请求. 服务端接收请求并响应. 服务端返回数据给客户端. 对于Android客户端来说,最重要的也就莫过于获取服务端返回的数据来展示了. 那么,首先我们要知道服务端返回的数据

网络编程四:互联网中TCP Socket服务器的实现过程需要考虑哪些安全问题

这篇曾经是答在这里的 互联网中TCP Socket服务器的实现过程需要考虑哪些安全问题- auxten 的回答 最近总是有人问我相关的问题,在专栏补发一下,希望能帮到更多人 首先,这是个很大的命题,之前在360负责过几个对外的服务的研发,也算是有点小经验,我试着答一下 在Internet环境下安全问题我主要分为如下几类 1. 信息传输过程中被黑客窃取 2. 服务器自身的安全 3. 服务端数据的安全 首先,如果能用https,就尽量用https,能用nginx等常见服务器,就用常见服务器,主要能避

Android开发中网络编程与常见功能优化总结

Android提供的AsyncTask,但事实上AsyncTask的问题更加严重,Thread只有在run函数不结束时才出现这种内存泄露问题,然而AsyncTask内部的实现机制是运用了 ThreadPoolExcutor,该类产生的Thread对象的生命周期是不确定的,是应用程序无法控制的,因此如果AsyncTask作为Activity的内部类,就更容易出现内存泄露的问题. 一般的应用都是从服务器获取数据,然后通过极致的界面风格,将数据清晰,明朗的展现给用户. 那么就可以分为这两块: 1.界面

Java高并发网络编程(四)Netty

在网络应用开发的过程中,直接使用JDK提供的NIO的API,比较繁琐,而且想要进行性能提升,还需要结合多线程技术. 由于网络编程本身的复杂性,以及JDK API开发的使用难度较高,所以在开源社区中,涌现出来了很多对JDK NIO进行封装.增强的网络编程框架,比如Netty.Mina等. 一.Netty简介 https://netty.io/ 官网 Netty是一个高性能.高可扩展性的异步事件驱动的网络应用程序框架,它极大简化了TCP和UDP客户端和服务器开发等网络编程. Netty重要的四个内容

Unix 网络编程(四)- 典型TCP客服服务器程序开发实例及基本套接字API介绍

写在开头: 在上一节中我们学习了一些基础的用来支持网络编程的API,包括"套接字的地址结构"."字节排序函数"等.这些API几乎是所有的网络编程中都会使用的一些,对于我们正确的编写网络程序有很大的作用.在本节中我们会介绍编写一个基于TCP的套接字程序需要的一些API,同时会介绍一个完整的TCP客户服务器程序,虽然这个程序功能相对简单,但确包含了一个客户服务器程序所有的步骤,一些复杂的程序也都是在此基础上进行扩充.在后面随着学习的深入,我们会给这个程序添加功能. 下面

Android应用开发-网络编程(一)(重制版)

网络图片查看器 1. 确定图片的网址 2. 发送http请求 URL url = new URL(address); // 获取客户端和服务器的连接对象,此时还没有建立连接 HttpURLConnection conn = (HttpURLConnection) url.openConnection(); // 设置请求方法,注意必须大写 conn.setRequestMethod("GET"); // 设置连接和读取超时 conn.setConnectTimeout(5000); c

Android中的网络编程

谷歌在Android6.0之后就废弃了使用HttpClinet进行网络连接.所以,这里需要重点学习的是通过HttpUrlConnect进行网络连接. String path="这里是你想要的连接"; URL url=new URL(path); HttpURLConnection huc=(HttpURLConnection)url.openConnection(); huc.setConnectTimeout(3000); huc.setReadTimeout(3000); //请求