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

来源:互联网 发布:安卓 数据恢复 编辑:程序博客网 时间:2024/06/03 21:31

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

在编写网络应用时,我们经常会用到发送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操作,要使用异步消息处理机制。

0 0