<<第一行代码>>--自定义HttpUtils类并使用回调获取服务器返回数据

在<<第一行代码>>一书中学习到的技巧,再此实验整合:

在编写网络应用时,我们经常会用到发送Http请求的地方,然而每次发送Http请求的代码几乎是相同的,所以通常情况下,我们将这些通用的网络操作提取到一个公共类里,并提供一个静态方法。(类似简单工厂模式)

以使用HttpURLConnection为例。

public class HttpUtils {

    public static InputStream sendHttpRequest(final String address) {
        HttpURLConnection connection = null;
        try {
            URL url = new URL(address);
            connection = (HttpURLConnection) url.openConnection();
            connection.setDoInput(true);
            connection.setRequestMethod("GET");
            connection.setReadTimeout(5000);
            connection.setDoOutput(true);

            InputStream inputStream = connection.getInputStream();

            //返回一个输入流
            return inputStream;

        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (ProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (connection != null)
                connection.disconnect();
        }

        return null;

    }
}

以后每当发起一条请求就可以简单写成:

String address = "http://www.baidu.com";
//发送get请求,获取输入流
InputStream is= HttpUtils.sendHttpRequest(address);

此时会有一个问题,网络请求通常是耗时操作,而在方法中我们没有开启一个子线程进行网络操作,这样就有可能调用sendHttpRequest()方法时阻塞主线程。

而正因为耗时操作都在子线程中进行,如果我们在sendHttpRequest( )方法中开启一个子线程进行通信,那么服务器返回的数据是无法及时传递的,因为sendHttpRequest( )方法会在服务器还没来得及响应时就执行结束了,也就无法返回响应的数据了。

解决方案:采用JAVA回调机制

先自定义一个接口:

public interface HttpCallbackListener{
    //当服务器成功响应的时候调用
    void  onFinish(String response);
    //当网络操作出现错误的时候我们调用
    void onError(Exception e);
}

然后修改HttpUtils中代码:

public class HttpUtils {

    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.setDoInput(true);
                    connection.setRequestMethod("GET");
                    connection.setReadTimeout(5000);
                    connection.setDoOutput(true);

                    InputStream inputStream = connection.getInputStream();

                    if (listener!=null){
                        //回调onFinish()
                        listener.onFinish (inputStream);
                    }
                } catch (Exception e) {
                    if (listener!=null){
                        //回调onError()
                        listener.onError (e);
                    }
                }  finally {
                    if (connection != null)
                        connection.disconnect();
                }
            }
        }).start ();
    }
}

即在子线程中不返回数据,而将服务器返回的数据交给传递给接口,在接口中接收流并进行操作,如果出现异常则传入到onError()方法中。

在调用时要传入两个参数了

HttpUtils.sendHttpRequest (address, new HttpCallBackListener () {
            @Override
            public void onFinish (InputStream inputStream) {
                //对返回内容执行操作
            }

            @Override
            public void onError (Exception e) {
                //对异常进行处理
            }
        });

到这里,若是服务器返回数据成功,则返回数据交给调用方处理;若获取数据异常,则将错误信息交给调用方处理。

另外,onFinish( )和onError( )仍然是在子线程中运行的,因此不可以在里面执行UI操作,要使用异步消息处理机制。

你可能感兴趣的:(安卓,网络,网络应用,工厂模式,HttpUtil)