OKHttp
文章目录
一、简介
OKHttp是一款优秀的HTTP框架,他支持get请求和get请求,支持基于http的文件上传和下载,支持加载图片,支持下载文件透明的GZIP压缩,支持响应缓存避免重复的网络请求,支持使用连接池来降低响应延迟问题。
OKHttp不仅在接口封装上面做的简单易用,就连在底层实现上也是自成一派,比起原生的HttpURLConnection,可以上市有过而过之不及,现在就是成为广大Android开发者首选的网络通信库。
OKHttp的项目主页地址时:https://github.com/square/okhttp
注意:OkHttp有2.0版本和3.0的版本,目前常用的是OkHttp3。
二、基本用法
1、依赖
在使用之前先添加OKHttp库的依赖,编辑app/build.gradle文件在dependencies闭包中添加如下内容:
implementation 'com.squareup.okhttp3:okhttp:4.4.0'
也可以通过工具,在项目中添加OKHttp库的依赖
2、使用OKHttp
2.1、get请求
步骤一:创建OKHttpClient类的实例
OkHttpClient client = new OkHttpClient();
步骤二:创建Request对象(并设置目标地址、请求方式等)
//需要在build()方法前连缀其他方法来丰富这个Request对象
Request request = new Request.Builder()
.url(“https://www.baidu.com”) //设置目标网络地址
.get() //默认为GET请求,可以省略
.build();
步骤三:调用newCall()方法创建call对象
Call call = client.newCall(request);
步骤四:发送请求并获取服务器返回的数据(同步、异步)
同步请求:
执行请求的操作是阻塞式,直到HTTP响应返回。如果当前OkHttpClient已经执行了一个同步任务,如果这个任务没有释放锁,那么新发起的请求将被阻塞,直到当前任务释放锁。同步请求对应OkHttp中的execute()方法。
//因为同步请求的方式会阻塞调用线程,所以提交同步请求的操作应放在子线程中执行,否则有可能会引起ANR异常,并且在Android 3.0以后已经不允许在主线程中进行网络操作了。
new Thread(new Runnable() {
public void run() {
try {
Response response = call.execute();
String responseData = response.body().string();
Log.d(TAG, "run: " + responseData);
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
异步请求:
执行的是非阻塞式请求,它的执行结果一般都是通过接口回调的方式告知调用者。同一时刻可以发起多个请求,因为异步请求每一个都是在一个独立的线程,由线程队列管理。异步请求对应OkHttp中的enqueue()方法。
//通过Call对象的enqueue(Callback)方法来提交异步请求,异步发起的请求会被加入到队列中通过线程池来执行。最后通过接口回调的onResponse()方法来接收服务器返回的数据。
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.d(TAG, "onFailure: ");
}
@Override
public void onResponse(Call call, Response response) throws IOException {
String responseData = response.body().string();
Log.d(TAG, "onResponse: " + responseData);
}
});
2.2、post请求
步骤一:创建OKHttpClient类的实例
OkHttpClient client = new OkHttpClient();
步骤二:创建Request对象
如果是发起一条POST请求会比GET请求稍微复杂一点,在构建Request对象时,需要多构造一个RequestBody对象,用它来携带我们要提交的数据。
在构造RequestBody时需要指定MediaType,用于描述请求/响应body的内容类型。RequestBody的几种常用构造方式如下:
create( String content, MediaType contentType) //提交String类型数据
create( byte[] content ,MediaType contentType) //提交byte[]类型数据
create( File file , MediaType contentType) //提交File类型数据
使用FormBody提交表单,同时在FormBody中添加多个String键值对,最后为Request添加post方法并传入FormBody。
RequestBody requestBody = new FormBody.Builder()
.add(“username”,”admin”)
.add(“password”,”123456”)
.build();
Request request = new Request.Builder()
.url(“https://www.baidu.com”)
.post(requestBody)
.build();
后面一样,略。
3、案例操作演示(借助runOnUiThread()方法进行线程切换)
加入依赖
xml文件
activity文件
添加访问网络请求
4、使用回调方法请求网络
HttpUtil类:
public class HttpUtil{
public static void sendOkHttpRequest(String address,okhttp3.Callback callback){
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(address)
.build();
client.newCall(request).enqueue(callback);
}
}
Okhttp3.Callback
因为OkHttp库中自带了一个回调接口Callback,类似于前面编写的HttpCallbackListener。
通过调用enqueue()方法,其内部不仅开好了子线程,同时还会在子线程中去执行HTTP请求,最后将请求的结果回调到Callback接口中。
OKHttp封装:调用HttpUtil类中的sendOkHttpRequest()方法
HttpUtil.sendOkHttpRequest(“https://www.baidu.com”,new okhttp3.Callback(){
@Override
public void onResponse(Call call,Response response) throws IOException {
//得到服务器返回的具体内容
String responseData = response.body().string();
}
@Override
public void onFailure(Call call,IOException e){
//对异常情况进行处理
}
});
注意:
不管是HttpURLConnection还是OkHttp,最终的回调接口都还是在子线程中进行的,因此不可以在回调接口中执行任何的UI操作。
方法1:借助runOnUiThread()方法进行线程切换。
runOnUiThread(new Runnable() {
@Override
public void run() {
......
}
});
方法2:通过Handler对象传递消息给主线程。
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
Object obj = msg.obj;
ivPic.setImageBitmap((Bitmap) obj);
}
};
Message message = new Message();
message.obj = bitmap;
handler.sendMessage(message);
5、案例操作演示(通过Handler对象传递消息给主线程。)
通过网络图片的地址获取图片
xml页面:里面一个ImageView控件,这里略
回调接口:okhttp3.Callback(OKHttp自带的回调接口)
工具类:HttpUtil02
public class HttpUtil02 {
public static void sendOkHttpRequest(final String address,okhttp3.Callback callback){
OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder()
.url(address)
.get()
.build();
Call call = okHttpClient.newCall(request);
call.enqueue(callback);
}
}
activity:
public class OKHttpActivity04 extends AppCompatActivity {
private EditText et_path;
private ImageView ivPic;
private Bitmap bitmap;
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
Object obj = msg.obj;
ivPic.setImageBitmap((Bitmap) obj);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_1_1);
et_path = findViewById(R.id.et_path);
ivPic = findViewById(R.id.iv_pic);
}
public void click(View view) {
String s = et_path.getText().toString();
HttpUtil02.sendOkHttpRequest(s, new okhttp3.Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
InputStream in = response.body().byteStream();
bitmap = BitmapFactory.decodeStream(in);
Message message = new Message();
message.obj = bitmap;
handler.sendMessage(message);
}
});
}
}