Google在Android6.0以后就删除HttpClient相干的API,使用HttpUrlConnection代替,在Android开发中,网络访问是必不可少的,网络上也有很多网络操作的框架,这1篇,我们介绍1下网络上非常火的1个网络框架——Okhttp框架。
Okhttp现在已出到3.4.1版本,主要包括的功能有:
1般的get要求
1般的post要求
基于Http的文件上传
文件下载
加载图片
支持要求回调,直接返回对象、对象集合
支持session的保持
下面我们介绍1下Okhttp的简单使用:
使用Okhttp需要在项目的gradle文件中导入包,直接添加以下代码:
compile 'com.squareup.okhttp3:okhttp:3.4.1'
不过建议先去okhttp的github上查看最新的版本,okhttp的github地址是:https://github.com/square/okhttp
使用Eclipse的话需要下载相应的JAR包,也能够到上述地址下载。
还有需要在清单文件中添加联网的权限
<uses-permission android:name="android.permission.INTERNET"/>
完成准备工作以后,我们就而已开始使用这个网络框架了,下面我们通过具体的例籽实现以下okhttp的各种功能:
//异步get要求
findViewById(R.id.tv_async_get).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
OkHttpClient okHttpClient = new OkHttpClient();
Request.Builder builder = new Request.Builder();
Request request = builder.url("http://blog.csdn.net/lmj623565791/article/details/49734867").method("GET", null).build();
Call call = okHttpClient.newCall(request);
//回调监听
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this, "异步get要求失败", Toast.LENGTH_SHORT).show();
}
});
}
@Override
public void onResponse(Call call, Response response) throws IOException {
// if (response.cacheResponse() != null) {
// String str = response.cacheResponse().toString();
// Log.i(TAG, "onResponse" + str);
// } else {
// String str = response.networkResponse().toString();
// Log.i(TAG, "onResponse" + str);
// }
Log.i(TAG, "===============================================================================");
String str = response.body().string();
Log.i(TAG, "onResponse" + str);
Log.i(TAG, "===============================================================================");
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this, "异步get要求成功", Toast.LENGTH_SHORT).show();
}
});
}
});
}
});
这里就是构建1个要求回调,不过回调不是在主线程,所以不能直接更新UI
//同步get要求
findViewById(R.id.tv_sync_get).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new Thread(new Runnable() {
@Override
public void run() {
OkHttpClient okHttpClient = new OkHttpClient();
Request.Builder builder = new Request.Builder();
Request request = builder.url("http://www.baidu.com").method("GET", null).build();
Call call = okHttpClient.newCall(request);
try {
Response response = call.execute();
if (response.isSuccessful()) {
Log.i(TAG, "=======================================================");
Log.i(TAG, "run" + response.body().string());
Log.i(TAG, "=======================================================");
runOnUiThread(new Runnable() {
@Override
public void run() {
Log.i(TAG, "同步get要求成功");
Toast.makeText(MainActivity.this, "同步get要求成功", Toast.LENGTH_SHORT).show();
}
});
} else {
runOnUiThread(new Runnable() {
@Override
public void run() {
Log.i(TAG, "同步get要求失败");
Toast.makeText(MainActivity.this, "同步get要求失败", Toast.LENGTH_SHORT).show();
}
});
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
});
同步GET要求和异步GET要求最大的区分就是调用不同的方法,同步调用的是execute,而异步调用的是enqueue,网络要求不能主线程中。
客户端代码:
//异步post要求
findViewById(R.id.tv_async_post).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
OkHttpClient okHttpClient = new OkHttpClient();
RequestBody formBody = new FormBody.Builder().add("username", "zhangsan")
.add("password", "zhangsan").build();
Request resuest = new Request.Builder().post(formBody).url("http://192.168.0.218:8080/sayHello").build();
Call call = okHttpClient.newCall(resuest);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this, "服务器没法连接", Toast.LENGTH_SHORT).show();
}
});
}
@Override
public void onResponse(Call call, Response response) throws IOException {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this, "post要求成功", Toast.LENGTH_SHORT).show();
}
});
}
});
}
});
服务器端:
服务器端我是用Intelij IDEA2016写的,就是简单实现上传两个字符串而已,代码也非常简单。
//异步下载文件
findViewById(R.id.tv_async_download_file).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder().url("http://192.168.0.218:8080/okhttp⑶.4.1.jar").build();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this, "下载失败,请稍后重试", Toast.LENGTH_SHORT).show();
}
});
}
@Override
public void onResponse(Call call, Response response) throws IOException {
InputStream inputStream = response.body().byteStream();
FileOutputStream fileOutputStream = null;
fileOutputStream = new FileOutputStream(new File("/sdcard/okhttp⑶.4.1.jar"));
byte[] bytes = new byte[1024];
int len = 0;
while ((len = inputStream.read(bytes)) != ⑴) {
fileOutputStream.write(bytes, 0, len);
}
fileOutputStream.flush();
Log.i(TAG, "onResponse----->>文件下载成功");
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this, "文件下载成功", Toast.LENGTH_SHORT).show();
}
});
}
});
}
});
实现的效果以下:
//异步上传文件
findViewById(R.id.tv_async_upload_file).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
MediaType mime = MediaType.parse("application/java-archive;charset=utf⑻");
String url = "http://192.168.0.218:8080/upload";
OkHttpClient okHttpClient = new OkHttpClient();
File file = new File("/sdcard/okhttp⑶.4.1.jar");
Request request = new Request.Builder().url(url).post(RequestBody.create(mime, file)).build();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.i(TAG, "onResponse---->>上传失败");
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this, "文件上传失败", Toast.LENGTH_SHORT).show();
}
});
}
@Override
public void onResponse(Call call, Response response) throws IOException {
Log.i(TAG, "onResponse---->>上传成功");
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this, "文件上传成功", Toast.LENGTH_SHORT).show();
}
});
}
});
}
});
文件上传需要用服务器接收,这里我是自己写1个简单的Servlet去接收的,实际开发肯定会有服务器接收的。这里需要注意的是需要设置文件的MIME类型,如果不知道相应后缀名的文件的MIME类型,可以去这里查看1下:http://www.cnblogs.com/linyijia/p/5466317.html
与前面版本不同的是,3.0以后就不再允许直接通过OkhttpClient设置超时了,而是通过OkHttpClient.Builder设置,设置好以后我们可以直接通过builder.build获得到1个OkHttpClient,这样我们就不再需要new1个OkHttpClient。请看下面的代码:
OkHttpClient.Builder builder = new OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.writeTimeout(20, TimeUnit.SECONDS)
.readTimeout(20, TimeUnit.SECONDS)
.cache(new Cache(sdcache.getAbsoluteFile(), cacheSize));
OkHttpClient mOkHttpClient=builder.build();
可以直接调用call.cancel()取消掉要求,这个框架的2次封装网上有很多,这里就不再贴代码了,关于这个框架就简单介绍到这里了,推荐几篇关于这个框架的介绍博文:
Android 1个改良的okHttp封装库
OkHttp3源码分析
okhttp3与旧版本okhttp的区分分析