好几天没写了,最近迷上了Material Design下次会写一章,好好说说。不过在学的过程中也发现自己的基础还是不行,沉下心来好好把剩下的基础部分复习一下还是很有必要的。
今天写一个大话题。
网络编程
网络部分在之后工作中绝对是必不可少的,之前的JavaWeb部分也提到过servlet,http有get和post两种请求模式。
1. get请求是在发送http请求时直接将携带的信息在链接中携带,这样弊端很明显,首先他携带的信息量并不能太多,而且这样的请求方式并不安全,但他确实较为方便。
2. post请求拥有请求体,使用请求体携带数据,安全,携带量大,但同时使用上了请求体也显得麻烦了一丁点儿。
3. android同样使用的是get与post请求。
预备知识
在使用设备网络时首先需要拥有这样一个权限:
<uses-permission android:name="android.permission.INTERNET"/>
android4.0版本之后,google强制要求访问网络的操作不允许在主线程中执行,只能创建子线程执行,访问网络属于一项耗时操作,如果放在主线程运行,会影响界面运行时的流畅性。
这样的耗时操作还有:- 文件下载。
- 音频格式转换操作。
- 文件操作。
- 比较大的数据的初始化操作。
- sleep函数等 。
之后会介绍一些关于异步任务的知识,使用AsyncTask创建异步任务,处理耗时操作,并与主线程通信。
- 在主线程中进行一些耗时操作的时候,会报出ANR异常:Application Not Response,这是由于耗时操作阻塞了主线程,用户点击时主线程无法进行相对应的响应呢,然后报出ANR异常。
- Activity的onCreate方法以及点击事件都是运行在主线程中,主线程实时体现出来的就是UI界面,所以主线程也叫UI线程。而同样的子线程是不能执行修改UI的操作的,除非使用looper。
- 在子线程执行了耗时操作之后,得出了结果,但是这也需要响应在UI上时,我们会使用到handler,handler是用于线程间通信的,使用在子线程中使用handler创建message对象,鞋带上子线程中的数据类型与数据内容发送至主线程的handler,之后用于显示UI。
1. HttpURLConnection
这是最基础的,android最基本的http网络访问的编程方式
- 接下来直接在代码中进行介绍了
new Thread(new Runnable() {
@Override
public void run() {
String path = "http://10.0.3.2:8080/Test/Login";
try {
URL url = new URL(PATH + "?username=" + username + "&password=" + password);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setConnectTimeout(TIME_OUT);
connection.connect();
int responseCode = connection.getResponseCode();
if (responseCode == 200) {
InputStream is = connection.getInputStream();
//流转字符串工具,过程省略
String result = StreamUtils.is2Str(is);
Message msg = new Message();
msg.what = 1;
msg.obj = result;
handler.sendMessage(msg);
} else {
handler.obtainMessage(2, responseCode).sendToTarget();
}
} catch (Exception e) {
e.printStackTrace();
handler.obtainMessage(3, e).sendToTarget();
}
}
}).start();
}
接下来来简单分析一下流程:
- 创建子线程,覆写run方法。
- 创建URL对象,即为GET请求的具体的URL,由初始的链接与数据组成,这里模拟一个登陆,get请求在链接中直接携带账号与密码进行请求。
- 使用url对象打开链接,创建HttpURLConnection对象
- 设置请求时限,超时则直接报错。
- 连接
- 使用HttpURLConnection对象的getResponse方法获取响应码
- 在这之后,由连接情况进行分析响应码,200即为访问成功,之后就是获取连接数据了。
- 使用HttpURLConnection对象的getInputStream获取流对象,而这之后省略的部分是读取流,然后存储了一个字符串对象,而这个字符串即是最后的结果。
在使用Message对象之前,我们在主线程已经创建了一个handler对象,并覆写handleMessage方法:
private Handler handler = new Handler() { @Override public void handleMessage(android.os.Message msg) { switch (msg.what) { case 1: Toast.makeText(MainActivity.this, "请求成功:" + msg.obj, Toast.LENGTH_SHORT).show(); break; case 2: Toast.makeText(MainActivity.this, "状态码不正确:" + msg.obj, Toast.LENGTH_SHORT).show(); break; case 3: Toast.makeText(MainActivity.this, "异常:" + msg.obj, Toast.LENGTH_SHORT).show(); break; default: break; } }; };
使用Handler分别处理三中message对象,而分别信息类型的方式是依据子线程中message绑定的what。三种不同的数据类型,显示三种不同的结果。
- 在子线程中先创建Message对象,为msg.what赋值,用于在handler中分辨数据类型,之后使用msg.obj创建这个object类型的对象,将数据结果result赋值,传递到handler中。
HttpURLConnection具体流程基本如上,而post方法需要改变的只是定义HttpURLConnection对象的setRequestMethod(“post”);以及在创建url、对象时,地址不需要再添加数据。之后使用其getOutputStream方法获取输出流,将数据写入。之后的流程与get相同。
2. HttpClient
- HttpClient是apache开源组织研发的api,它是一个简单的HTTP客户端,能够发送和接收http请求和响应。HttpClient设计思想是模拟浏览器的操作来实现网络访问。
- Android成功了集成了HttpClient,所以在Android项目中可以直接使用HttpClient来想Web站点提交请求以及接受响应。
- HttpClient是一个interface类型,HttpClient封装了对象需要执行的Http请求,身份验证,连接管理和一些其他特性。它提供了三个实现类,而也专门为Android应用提供了一个实现类AndroidHttpClient,相对于DefaultHttpClient做了一些改进:
- 关掉了过期检查,自连接可以打破所有的时间限制。
- 可以设置ConnectionTimeOut(连接超时)和SoTimeout(读取时间超时)。
- 关掉了重定向。
- 如果服务器支持,使用gzip压缩方式用于在服务器和客户端传递的数据。
- 默认情况下不保留Cookie
- 使用一个Session缓冲用于SSL Sockets。
这些东西只需要了解,以后并不会用了,并且在6.0之后不再支持。
使用步骤:
在使用之前需要创建子线程。
- 定义一个客户端对象:即获得一个HttpClient对象,等同于打开浏览器。
- 定义请求方法GET/POST,等同于在浏览器输入网址。
- 设置请求的参数/其牛头信息/连接超时时间/读取数据超时时间等。
- execute方法执行请求,等同于敲回车,此方法会返回一个HttpResponse对象。
- 获取了HttpResponse对象之后,获取其状态码,getStatusLine().getStatusCode()。
- 如果状态码为200,获取服务器返回的数据流,getEntity().getContent()。
- 结束操作后断开连接,getConnectionManager().shutdown()。
1.GET请求方式
public void HttpClientTest(){
new Thread(){
@Override
public void run() {
super.run();
String path = PATH+"?username="+username+"&pwd="+pwd;
//1.获取一个客户端对象
HttpClient client = new AndroidHttpClient();
//2.定义请求方式,并传递请求地址
HttpGet httpGet = new HttpGet(path);
//3.获取参数对象
HttpParams params = httpGet.getParams();
//4.设置链接超时时间
HttpConnectionParams.setConnectionTimeout(params,
5000);
//5.设置读取数据超时时间
HttpConnectionParams.setSoTimeout(params, 5000);
//6.开始发送请求,同时返回HttpResponse 对象,该句代码属于耗
时操作
HttpResponse httpResponse = client.execute(httpGet);
//7.获取状态码
int code =
httpResponse.getStatusLine().getStatusCode();
if (code==200) {
//8.获取返回数据流对象
InputStream in =
httpResponse.getEntity().getContent();
ByteArrayOutputStream bos = new
ByteArrayOutputStream();
byte[] buff = new byte[1024];
int len;
while((len=in.read(buff))!=-1){
bos.write(buff, 0, len);
}
in.close();
result = bos.toString();
bos.close();
}else {
result = "请求失败!";
}
//9.关闭链接
client.getConnectionManager().shutdown();
}
}
2.POST请求方式
//1.创建客户端对象
HttpClient client = new AndroidHttpClient();
//2.创建一个POST 请求对象
HttpPost httpPost = new HttpPost(PATH);
//3.获取请求对象的参数
HttpParams httpParams = httpPost.getParams();
//4.设置链接超时时间
HttpConnectionParams.setConnectionTimeout(httpParams, 5000);
//5.设置读取数据流超时时间
HttpConnectionParams.setSoTimeout(httpParams, 5000);
//6.设置请求参数集合,将请求参数都添加到该集合
List<BasicNameValuePair> parameters = new
ArrayList<BasicNameValuePair>();
//7.将用户信息添加到集合中
parameters.add(new BasicNameValuePair("username", username));
parameters.add(new BasicNameValuePair("pwd", pwd));
//8.创建一个请求体对象
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(parameters );
//9.给httpPost 对象设置请求体
httpPost.setEntity(entity);
HttpResponse httpResponse = client.execute(httpPost);
//10.获取状态码
int code = httpResponse.getStatusLine().getStatusCode();
if (code==200) {
//11.获取返回数据流对象
InputStream in = httpResponse.getEntity().getContent();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] buff = new byte[1024];
int len = -1;
while((len=in.read(buff))!=-1){
bos.write(buff, 0, len);
}
in.close();
result = bos.toString();
bos.close();
}else {
result = "请求失败!";
}
//12.关闭链接
client.getConnectionManager().shutdown();
3.AsyncHttpClient
- AsyncHttpClient是一个Android的异步Http函数库,属于开源框架,##它无需开启子线程##,因为调用其方法时传递的接口参数中的方法就是执行在主线程中的。
- github地址:https://github.com/loopj/android-async-http,使用前仔细阅读README,将依赖添加至gradle:compile
com.loopj.android:android-async-http:1.4.9
1.GET请求
//创建一个AsyncHttpClient 对象
AsyncHttpClient client = new AsyncHttpClient();
//调用get 方法,发送get 方式的请求
client.get(PATH, new AsyncHttpResponseHandler() {
/**
* 处理成功的结果
* statusCode 状态码
* headers 响应头消息
* responseBody 相应的主体内容
*/
@Override
public void onSuccess(int statusCode, Header[] headers,byte[] responseBody) {
String result = new String(responseBody);
Toast.makeText(MainActivity.this, "请求结果:"+result,1).show();
}
/**
* 处理失败的结果
* statusCode 状态码
* headers 响应头消息
* responseBody 相应的主体内容
*/
@Override
public void onFailure(int statusCode, Header[] headers,byte[] responseBody, Throwable throwable) {
Toast.makeText(MainActivity.this, "请求网络失败!",0).show();
}
});
2.POST方式
基本逻辑与GET方式相同,GET方式将请求参数凭借在URL后面传输给服务器,POST方式需要使用RequestParams对象封装请求参数给post。
AsyncHttpClient client = new AsyncHttpClient();
RequestParams params = new RequestParams();
params.put("username", "heima");
params.put("pwd", "12346");
client.post(PATH, params,new AsyncHttpResponseHandler() {
//相同代码省略
});
这部分属于过时的方法,但是需要了解他的思想
4.okhttp
这部分稍微查了一下,就看见张大神的博客了,直接贴出来吧:
Android OkHttp完全解析 是时候来了解OkHttp了
【张鸿洋的博客】
不仅如此,在他的github上也对okhttp的各项功能都进行了进一步的封装:
这在今后进行网络的开发中非常常用,6.0中也删除了httpClient相关的API。而okhttp便是最常用的网络请求框架了。
5.volley
由于volley底层使用HttpClient,无法兼容6.0版本,使用时可以将编译版本改为22,但不建议使用。
Android Volley完全解析(一),初识Volley的基本用法
6.Retrofit
未完待续。。。