Android开发中给服务器发送Http请求获取响应
2016-03-14 18:12
756 查看
在android中,有很多的情况都要用到网络的功能,而发送HTTP请求的代码基本上是一样的。所以我觉得很有必要将这些通用的操作提取到一个公共类里,并提供一个静态的方法,当想要发起网络请求的时候只需要简单的调用一下这个方法即可。发送HTTP请求的方式在安卓开发中一般有两种,HttpURLConnection和HttpClient。在这里采用HttpURLConnection的写法:
public class HttpUtil {
public static String sendHttpRequest(String address) {
private HttpURLConnection connection;
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 builder = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
builder.append(line);// 一行行的读取内容并追加到builder中去
}
return builder.toString();
} catch (Exception e) {
e.printStackTrace();
return e.getMessage();
} finally {
if (connection != null) {
connection.disconnect();//连接不为空就关闭连接
}
}
}
}
以后每当发起一条HTTP请求的时候就可以这样写:
为什么可能会导致主线程阻塞呢?
这是因为在主线程中执行了耗时操作,如果耗时过久,就会使应用程序出现ANR异常,如果不知道这个异常的话自己百度一下就好了。一般主线程中用户的输入事件操作超过5s就会出现上述的异常,所以发送请求从服务器上获取数据是可能会导致主线程阻塞的。
你这时可能会说,很简单,在sendHttpRequest()方法内部开启一个线程不就解决这个问题了吗?其实不是你想的那么简单,如果我们在sendHttpRequest()方法中开启了一个线程来发HTTP请求,那么服务器响应的数据是无法进行返回的,所有的耗时操作逻辑都是在子线程里进行的,sendHttpRequest()方法会在服务器没来得及响应的时候就执行结束了,当然也就无法返回响应的数据了。
为什么会没响应就执行结束呢?
那是因为线程是并发的。懂了吗?不懂得话自己百度一下。
那么遇到上面说的"服务器没来得及响应的时候就执行结束了"这一情况,我们就要使用Java的回调机制了。下面来学习一下回调机制到底是如何使用的。
首先需要定义一个接口,比如将它命名为HttpCallbackListener,代码如下:
接着修改HttpUtil中的代码,如下:
这时候又有人会说这是为什么呢?
其实很简单,因为run()方法是没有返回值的。大家可以看看上面线程中的run()方法就知道了。
接下来怎么办?既然无法通过return语句返回数据,那么我们可以将服务器响应的数据传入HttpCallbackListener的onFinish()方法中,如果出现了异常就将异常原因传入到onError()方法中。
现在sendHttpRequest()方法接收两个参数了,因此我们在调用它的时候还需要将HttpCallbackListener的实例传入,如下所示:
另外需要注意的是,onFinish()方法和onError()方法最终是运行在子线程中的,因此我们不可以在这里执行UI操作,如果需要根据返回的结果来更新UI,则要使用异步消息处理机制,即handler发消息。
每天进步一点点,加油!
public class HttpUtil {
public static String sendHttpRequest(String address) {
private HttpURLConnection connection;
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 builder = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
builder.append(line);// 一行行的读取内容并追加到builder中去
}
return builder.toString();
} catch (Exception e) {
e.printStackTrace();
return e.getMessage();
} finally {
if (connection != null) {
connection.disconnect();//连接不为空就关闭连接
}
}
}
}
以后每当发起一条HTTP请求的时候就可以这样写:
String address = "https://www.baidu.com"; String response = HttpUtil.sendHttpRequest(address);在获取到服务器的响应数据后我们就可以对它进行解析和处理了。但是需要注意的是网络操作属于耗时的操作,而sendHttpRequest()方法的内部并没有开启线程,这样就有可能导致在调用sendHttpRequest()方法的时候使得主线程被阻塞。
为什么可能会导致主线程阻塞呢?
这是因为在主线程中执行了耗时操作,如果耗时过久,就会使应用程序出现ANR异常,如果不知道这个异常的话自己百度一下就好了。一般主线程中用户的输入事件操作超过5s就会出现上述的异常,所以发送请求从服务器上获取数据是可能会导致主线程阻塞的。
你这时可能会说,很简单,在sendHttpRequest()方法内部开启一个线程不就解决这个问题了吗?其实不是你想的那么简单,如果我们在sendHttpRequest()方法中开启了一个线程来发HTTP请求,那么服务器响应的数据是无法进行返回的,所有的耗时操作逻辑都是在子线程里进行的,sendHttpRequest()方法会在服务器没来得及响应的时候就执行结束了,当然也就无法返回响应的数据了。
为什么会没响应就执行结束呢?
那是因为线程是并发的。懂了吗?不懂得话自己百度一下。
那么遇到上面说的"服务器没来得及响应的时候就执行结束了"这一情况,我们就要使用Java的回调机制了。下面来学习一下回调机制到底是如何使用的。
首先需要定义一个接口,比如将它命名为HttpCallbackListener,代码如下:
/** * 定义一个接口,接口中定义了两个方法 * @author Administrator * */ public interface HttpCallbackListener { void onFinish(String response);//当服务器成功响应的时候会调用该方法 void onError(Exception e);//当进行网络操作错误的时候会调用该方法 }可以看到,我们在接口中定义了两个方法,onFinish()方法表示当服务器成功响应我们请求的时候调用,onError()表示进行网络操作出现错误的时候调用,而onError()方法中的参数记录着错误的详细信息。
接着修改HttpUtil中的代码,如下:
package com.example.android_ydhl_system.util; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; public class HttpUtil { /** * 发送网络请求的时候调用该方法 * @param address URL对象 * @param listener 实例化的接口对象,回调方法需要实例化接口 */ public static void sendHttpRequest(final String address, final HttpCallbackListener listener) { new Thread() { private HttpURLConnection connection; public void run() { 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 builder = new StringBuilder();// 创建一个StringBuilder对象 String line; while ((line = reader.readLine()) != null) { builder.append(line);// 一行行的读取内容并追加到builder中去 } if (listener != null) { // 回调onFinish()方法 listener.onFinish(builder.toString()); } } catch (Exception e) { e.printStackTrace(); // 回调onError()方法 listener.onError(e); } finally { if (connection != null) { connection.disconnect();//连接不为空就关闭连接 } } }; }.start(); } }我们首先给sendHttpRequest()方法添加了一个HttpCallbackListener参数,并在方法的内部开启了一个子线程,然后在子线程里去执行具体的网络操作。注意子线程中是无法通过return语句来返回数据的。
这时候又有人会说这是为什么呢?
其实很简单,因为run()方法是没有返回值的。大家可以看看上面线程中的run()方法就知道了。
接下来怎么办?既然无法通过return语句返回数据,那么我们可以将服务器响应的数据传入HttpCallbackListener的onFinish()方法中,如果出现了异常就将异常原因传入到onError()方法中。
现在sendHttpRequest()方法接收两个参数了,因此我们在调用它的时候还需要将HttpCallbackListener的实例传入,如下所示:
HttpUtil.sendHttpRequest(address, new HttpCallbackListener() { @Override public void onFinish(String response) { Log.d("TAG", response.toString()); } @Override public void onError(Exception e) { } });这样的话,当服务器成功响应的时候我们就可以在onFinish()方法里对响应的数据进行处理了,类似地,如果出现了异常,就可以在onError()方法里对异常情况进行处理。如此一来,我们就其巧妙的利用回调机制将响应的数据成功返回给调用方了。
另外需要注意的是,onFinish()方法和onError()方法最终是运行在子线程中的,因此我们不可以在这里执行UI操作,如果需要根据返回的结果来更新UI,则要使用异步消息处理机制,即handler发消息。
每天进步一点点,加油!
相关文章推荐
- 利用Asp.Net回调机制实现进度条
- Android封装的http请求实用工具类
- 详解java模板和回调机制
- 深入浅析Android接口回调机制
- php 利用socket发送HTTP请求(GET,POST)
- 理解Java当中的回调机制(翻译)
- 突破”子网隔离”***C段
- Vxlan基础理解
- 初识Volley的基本用法
- SAN,NAS,DAS的区别
- 思科CallManager服务器备份与恢复操作手册
- CCNA寒假白班1月10号开班!火热报名中!
- OSI七层模型基础知识及各层常见应用
- 帧中继详解
- 如何开启Windows7的语音识别功能?
- 网吧光纤组网技术
- DNS的详细介绍与具体配置
- windows域控制器恢复
- OSPF全国网络互联实施方案
- 网管基本功