Android 中发起 HTTP
网络请求的方法有很多种,在刚开始学 Android 的时候,我总是比较倾向于使用原生提供的 API,其一是因为不需要导入第三方的依赖,其二是因为代码量也不多,而在实习后才发现,框架原来如此方便。
比如我需要写一个登录功能,希望使用 POST
方式提交,先来看看原生中的 HttpURLConnection
:
private void sendRequestWithHttpURLConnection(final String tel, final String password) {
new Thread(new Runnable() {
@Override
public void run() {
HttpURLConnection httpURLConnection = null;
try {
URL url = new URL("http://url"); // 接口
String data = "tel=" + tel + "&password=" + password;
httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.setConnectTimeout(8000); // 设置连接超时时间
httpURLConnection.setReadTimeout(8000); // 设置读取超时时间
httpURLConnection.setRequestMethod("POST"); // 设置以 Post 方式提交数据
DataOutputStream out = new DataOutputStream(httpURLConnection.getOutputStream());
out.writeBytes(data);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (httpURLConnection != null) {
httpURLConnection.disconnect();
}
}
}
}).start();
}
这里省略了部分代码,包括得到数据后的解析以及校验等等,代码并不多嘛,但是实际上跑起来就是,服务器上没有接收到我提交的数据。
几经周折,终于把残缺的代码补全了:
private void sendRequestWithHttpURLConnection(final String tel, final String password) {
new Thread(new Runnable() {
@Override
public void run() {
HttpURLConnection httpURLConnection = null;
try {
URL url = new URL("http://url"); // 接口
String data = "tel=" + tel + "&password=" + password;
httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.setConnectTimeout(8000); // 设置连接超时时间
httpURLConnection.setReadTimeout(8000); // 设置读取超时时间
httpURLConnection.setDoOutput(true); // 打开输出流,以便向服务器提交数据
httpURLConnection.setRequestMethod("POST"); // 设置以 Post 方式提交数据
httpURLConnection.setUseCaches(false); // 使用 Post 方式不能使用缓存
httpURLConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); //设置请求体的类型是文本类型
httpURLConnection.setRequestProperty("Content-Length", data.length() + ""); // 设置请求体的长度
httpURLConnection.connect(); // 建立连接
httpURLConnection.getOutputStream().write(data.getBytes());
int code = httpURLConnection.getResponseCode(); // 服务器的响应码 200 OK //404 页面找不到
// // 503服务器内部错误
if (code == 200) {
InputStream is = httpURLConnection.getInputStream();
// 把is的内容转换为字符串
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = -1;
while ((len = is.read(buffer)) != -1) {
bos.write(buffer, 0, len);
}
String result = new String(bos.toByteArray());
is.close();
Toast.makeText(LoginActivity.this, result, Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(LoginActivity.this, "请求失败,失败原因: " + code, Toast.LENGTH_SHORT).show();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (httpURLConnection != null) {
httpURLConnection.disconnect();
}
}
}
}).start();
}
我认为最重要的可能是这句:
httpURLConnection.connect(); // 建立连接
网上大多数的资料都没有提到,我就不知道他们是怎么连接的了,当我把这句代码补上后,App 才成功和服务器建立起连接。
另外下方关于服务器响应码的那段代码也是必须的,得到响应码,判断与服务器连接是否正常,没了这个判断就不能和服务器进行数据的交互。
这样看下来,跟一开始的“代码并不多”差距就太大了,代码冗余晦涩,阅读起来十分痛苦,于是便打算对这段代码进行重构。
之前阅读『第一行代码——Android』时有学习过 OkHttp
,所以我就打算使用它来代替 HttpURLConnection
。
为什么我虽然从一开始就知道这个网络通信库却不使用呢?因为前文也提到,我以为 HttpURLConnection
的代码量相比 OkHttp
并没有多出多少,但是出现了如此巨大的 Bug,修复完成后代码量居然增加了一倍,所以必须转投 OkHttp
的怀抱。
首先在项目中添加 OkHttp
库的依赖:
dependencies {
implementation 'com.squareup.okhttp3:okhttp:(insert latest version)'
}
为了使其保持最新版本,最好登录其官网或者其 Github 项目主页进行查询,当然,添加依赖时『Android Studio』内也会有提示。
然后就可以在项目中使用了,将上方的代码进行改造,就可以得出一段简洁的代码:
private void sendRequestWithOkHttp(final String tel, final String password) {
new Thread(new Runnable() {
@Override
public void run() {
try {
OkHttpClient client = new OkHttpClient();
RequestBody requestBody = new FormBody.Builder()
.add("tel", tel)
.add("password", password)
.build();
Request request = new Request.Builder()
.url("http://url") // 接口
.post(requestBody)
.build();
Response response = client.newCall(request).execute();
String responseCode = response.body().string();
Log.e("GETCODE", responseCode);
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
真的太好用了有木有!如此清晰简单的代码就完成了上面的内容,并且还十分容易获取从服务器返回的数据,方便我后面对其进行解析,简直要爱上它了!