美文网首页
实践:网络编程

实践:网络编程

作者: TTTqiu | 来源:发表于2016-05-09 15:13 被阅读50次
    • 一个应用程序很可能会在许多地方都使用到网络功能,而发送 HTTP 请求的代码基本都是相同的,如果我们每次都去编写一遍发送 HTTP 请求的代码,这显然是非常差劲的做法
    • 应该将这些通用的网络操作提取到一个公共的类里,并提供一个静态方法,当想要发起网络请求的时候只需简单地调用一下这个方法即可。
    public class HttpUtil {
        public static String sendHttpRequest(String address) {
            HttpURLConnection connection = null;
            try {
                URL url = new URL(address);
                connection = (HttpURLConnection) url.openConnection();
                connection.setRequestMethod("GET");
                connection.setConnectTimeout(8000);
                connection.setReadTimeout(8000);
                connection.setDoInput(true);
                connection.setDoOutput(true);
                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);
                }
                return response.toString();
            } catch (Exception e) {
                e.printStackTrace();
                return e.getMessage();
            } finally {
                if (connection != null) {
                    connection.disconnect();
                }
            }
        }
    }
    

    以后每当需要发起一条 HTTP 请求的时候就可以这样写:

    String address = "http://www.baidu.com";
    String response = HttpUtil.sendHttpRequest(address);
    
    • 但是 sendHttpRequest() 方法的内部并没有开启线程,这样就有可能导致在调用 sendHttpRequest() 方法的时候使得主线程被阻塞住。
    • 不能直接在 sendHttpRequest() 方法中开启一个线程来发起 HTTP 请求,因为这样,服务器响应的数据是无法进行返回的。所有的耗时逻辑都是在子线程里进行的,sendHttpRequest() 方法会在服务器还来不及响应的时候就执行结束了,也就无法返回响应的数据了
    • 需要使用 Java 的回调机制
    1. 先定义一个接口,比如将它命名成 HttpCallbackListener。
    public interface HttpCallbackListener {
        void onFinish(String response);
        void onError(Exception e);
    }
    
    • onFinish() 方法表示当服务器成功响应请求的时候调用。
    • onError() 表示当进行网络操作出现错误的时候调用。
    2. 修改 HttpUtil 中的代码。
    public class HttpUtil {
        public static void sendHttpRequest(final String address, final HttpCallbackListener listener) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    HttpURLConnection connection = null;
                    try {
                        URL url = new URL(address);
                        connection = (HttpURLConnection) url.openConnection();
                        connection.setRequestMethod("GET");
                        connection.setConnectTimeout(8000);
                        connection.setReadTimeout(8000);
                        connection.setDoInput(true);
                        connection.setDoOutput(true);
                        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());
                        }
                    } catch (Exception e) {
                        if (listener != null) {
                            // 回调onError()方法
                            listener.onError(e);
                        }
                    } finally {
                        if (connection != null) {
                            connection.disconnect();
                        }
                    }
                }
            }).start();
        }
    }
    
    • 注意子线程中是无法通过 return 语句来返回数据的
    • 因此将服务器响应的数据传入 HttpCallbackListener 的 onFinish() 方法中。
    • 如果出现了异常就将异常原因传入到 onError() 方法中。
    3. 现在 sendHttpRequest() 方法接收两个参数了,因此在调用它的时候还需要将 HttpCallbackListener 的实例传入。
    HttpUtil.sendHttpRequest(address, new HttpCallbackListener() {
        @Override
        public void onFinish(String response) {
            // 在这里根据返回内容执行具体的逻辑
        }
        @Override
        public void onError(Exception e) {
            // 在这里对异常情况进行处理
        }
    });
    
    • 需要注意的是,onFinish() 方法和** onError() 方法最终还是在子线程中运行的**,因此我们不可以在这里执行任何的 UI 操作.
    • 如果需要根据返回的结果来更新 UI,则仍然要使用异步消息处理机制。

    相关文章

      网友评论

          本文标题:实践:网络编程

          本文链接:https://www.haomeiwen.com/subject/gederttx.html