读书笔记–App研发录
Http和HttpUrlConnection的用法
标签(空格分隔): Android HttpUrlConnection 异步
网络请求过程
HTTP是一种应用层协议,他通过TCP实现了可靠的数据传输,能够保证数据的完整性,准确性,TCP的优点使得HTTP的数据传输吞吐量和效率得到保证。
移动开发多为C/S架构,客户端向服务端发送特定请求,服务器返回结构,客户端解析结果,再进行操作。
* 过程:
客户端执行网络请求,从URL中解析出服务器的主机名
主机名转换为IP地址
从URL中解析出端口号
建立客户端和服务器的TCP链接
客户端向服务器发送一条HTTP请求
服务器向客户端回执一条HTTP响应报文
客户端从输入流获取报文
客户端解析数据,关闭连接
客户端处理数据,并将结果显示在UI上
Request网络请求格式
对于网络请求,我们一般只需要定义GET和POST即可,GET为向服务器请求数据,POST为修改数据。但是HTTP支持的请求方式有很多,被人们常用的请求有7种。GET和DELETE的URL最大长度为1KB。
1,GET请求
http://www.xxx.com/aaa.api?k1=va&k3=v2
第一个参数之前有一个”?“,其后以”&“链接的键值对,是我们传输的参数。
2, POST请求
POST请求通常用来处理HTML的From表单,经常需要提交大量数据,所以我们的键值对要定义成集合或者复杂的自定义实体。这时可以将需要传输的值转换为JSON字符串进行提交,在底层MobileApi中完成JSON的实体化。
3,PUT请求
有些系统允许允许用户创建Web页面,PUT方法可以向服务器写入资源,如果已经存在请求主体的URL,用新的资源代替它。
4,DELETE请求
DELETE同样需要将参数放在URL中,不过HTTP规范允许服务器不通知客户端的情况下撤销请求,所以,无法保证指定的资源一定会被删除。
5,HEAD请求
HEAD和GET相似,但返回的数据不是数据的主体部分。使用HEAD请求可以在不获得资源的情况下获得资源的情况。通过查看响应中的状态码,可以判断对象是否存在。
6,TRACE请求
TRACE请求用于诊断,验证请求是否穿过了请求/响应链。客户端发起的请求可能要穿过代理,防火墙等,TRACE请求发送一个回环诊断,最后的服务器会返回原始的报文,让客户端判断请求是否能够正常到达服务器。
7,OPTIONS请求
询问服务器支持的方法,或者特殊资源支持的方法。
HTTP报文格式
格式是一个复杂的东西,有兴趣可以自己查一些资料。
Response格式
一般使用JSON作为MobileApi返回的结果
规范格式1
java
{
"isError" : true,
"errorType" : 1,
"errorMessage" : 网络异常,
"result" : ""
}
格式2
java
{
"isError" : false,
"errorType" : 0,
"errorMessage" : "",
"result" : [
{"id" : 1, "name" : "Brook"}
{"id" : 2, "name" : "Pirate"}
]
}
根据前面所说的实体化编程的规范,我们应该为Response建立一个对应的实体便于使用和保存。很简单,不必细说。如果result返回的是集合,则需要解析为相应的实体集合。
异常的类型的写法,因为网络原因标记为负数
,正常标记为0
,其他规定为正整数
底层获取过程
在原书的Demo中,2.12节,AsyncTask的使用和缺点,其中HttpClient
相关类已经不在支持,使用需要额外导入包useLibrary 'org.apache.http.legacy'
,sdk-23之后只支持HttpUrlConnection
, 因为他的API简单,较小,而且存在压缩与缓存机制,很适合Android。
在此使用HttpURLConnection代替HttpCilent,下面的代码可能有些不规范(缺少某些判断和异常处理,掌握基本用法即可。
public class WeatherAsync extends AsyncTask <String, Integer, Response> {
@Override
protected Response doInBackground(String[] params) {
return getResponseFromURL(params[0]);
}
private Response getResponseFromURL(String url) {
return getResponseFromString(
convertStreamToString(
getInputStreamFromURL(url)));
}
private InputStream getInputStreamFromURL(String url) {
InputStream is = null;
try {
URL newUrl = new URL(url);
HttpURLConnection connection = (HttpURLConnection) newUrl.openConnection();
// 读取超时10秒
connection.setReadTimeout(10000);
// 连接超时15秒
connection.setConnectTimeout(15000);
// 设置请求方式
connection.setRequestMethod("POST");
// 接受输入流
connection.setDoInput(true);
// 开启输出流, 需要传入参数,说明未开启
connection.setDoOutput(true);
// 添加请求Header
connection.setRequestProperty("Connection", "Keep-Alive");
// GET参数已经写在URL中,所以调用连接
connection.connect();
// 获取输入流
is = connection.getInputStream();
} catch (ProtocolException e1) {
e1.printStackTrace();
} catch (MalformedURLException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
return is;
}
private Response getResponseFromString(String result) {
Gson gson = new Gson();
Response response = gson.fromJson(result, Response.class);
return response;
}
private String convertStreamToString(InputStream is) {
String line;
try {
InputStreamReader inStreamReader = new InputStreamReader(is, "utf-8");
BufferedReader bufferedReader = new BufferedReader(inStreamReader);
while ((line = bufferedReader.readLine()) != null) {
return line;
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
}
关于网络访问底层框架的设计,建议看一看Android开发进阶-从小工到专家的4.3章-网络框架的设计与实现,了解一下原理即可。
本着不重复造轮子(造出来也跑不快)的原则,就可以使用OkHttp,Volley等框架。
参考 http://blog.csdn.net/caomiao2006/article/details/52648990[Http详解][1]