网络编程代码重用的一点问题与技巧

网络编程代码重用的一点问题与技巧

基本的重用代码事例

学习android开发时大家都会接触到发起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);
            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();
        } finally {
            if (reader != null){
                try {
                    reader.close();
                } catch (IOException e){
                    e.printStackTrace();
                }
            }
            if (connection != null){
                connection.disconnect();
            }
        }
    }

}

这样我们只需要传入网址,获取服务器相应的数据后,就可以进行后续的解析和处理了。

String address = "http://blog.dota2.com/"
String response = HttpUtil.sendHttpRequest(address);

线程是个问题

网络请求通常都是耗时的操作,而我们的sendHtttpRequest()方法内部并没有开启线程,这样可能会使主线程被阻塞住,这对用户的体验有不好的影响。
但我们恐怕也不能简单地在sendHtttpRequest()方法开启一个线程来解决问题。因为所有的耗时逻辑都在子线程进行的,sendHtttpRequest()方法会在服务器还没来得及响应的时候就执行结束了,导致该方法无法返回相应的数据。
所以我们需要另寻他路。

java的回调机制

我们先来看下面的代码:

public interface HttpCallBackListener {

    void onFinish(String response);

    void onError(Exception e);

}

我们定义了一个接口并在其中定义了两个方法,onFinish()在服务器相应请求时调用,参数是服务器返回的数据,onError()在进行网络操作出现错误时调用,参数是错误的详细信息。
然后修改HttpUtil的代码:

public class HttpUtil{

    public static String 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);
                    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) {
                        listener.onFinish(response.toString());
                    }
                } catch (Exception e){
                    if (listener != null) {
                        listener.onError(e);
                    }
                } finally {
                    if (reader != null){
                        try {
                            reader.close();
                        } catch (IOException e){
                            e.printStackTrace();
                        }
                    }
                    if (connection != null){
                        connection.disconnect();
                    }
                }
            }
        }).start;
    }

}

我们给sendHttpRequest()方法添加了一个HttpCallbackListener参数,并在方法的内部开启了一个子线程,由子线程去执行网络操作。由于子线程无法通过return语句返回数据,因此我们将数据传入了HttpCallbackListener的onFinish()方法中,而异常传入了onError()方法中。
现在,调用sendHttpRequest()方法的代码是这样的:

HttpUtil.sendHttpRequest("http://blog.dota2.com/", new HttpCallbackListener() {
    @Override
    public void onFinish(String response) {
        // 根据返回的数据执行具体逻辑
    }

    public void onError(Exception e) {
        // 在此处理异常
    }
});

如此一来,通过利用回调机制我们就解决了网络编程的线程问题。

使用OKHttp实现回调机制

有句话说得好,不要重复发明伦子,其实OKHttp已经提供了实现相同功能的接口,如下:

public static void sendOkHttpRequest(String address, okhttp3.Callback callback) {
    OkHttpClient client = new OkHttpClient();
    Request request = new Request.Builder().url(address).build();
    client.newCall(request).enqueue(callback);
}

sendOkHttpRequest传入了一个okhttp3.Callback参数,这是OkHttp库中自带的一个回调接口,类似于刚才的HttpCallbackListener。在client.newCall()之后调用enqueue()方法,并把okhttp3.Callback参数传入,没错,OkHttp会在enqueue()方法内部自己开好子线程并执行http请求,最终将请求结果回调到okhttp3.Callback当中。
所以,现在我们调用sendOkHttpRequest()方法是这样写:

HttpUtil.sendOkHttpRequest("http://blog.dota2.com/", new okhttp3.Callback() {
    @Override
    public void onResponse(Call call, Response response) throws IOException {
        // 根据返回的数据执行具体逻辑
        String responseData = response.body().string();
    }

    public void onFailure(Call call, IOException e) {
        // 在此处理异常
    }
});

这样,我们只需编写少量的代码就能完成较为复杂的网络操作了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值