in the past ,Android Send on HTTP There are generally two ways to request :HttpURLConnection and HttpClient(Apache HttpClient). But due to the HttpClient There is API Too many 、 It's difficult to expand ,Android The team is increasingly not suggesting that we use this approach . Finally in the Android 6.0 In the system ,HttpClient Has been completely removed , It indicates that this function has been officially abandoned . Although the official recommendation is HttpURLConnection, But in the process of code writing, it will still be more cumbersome . here , A network layer framework to replace them has emerged : That is to say Okhttp, The framework is also where I am 《Android First line of code 》 What you learn is nothing more than Litepal The second frame after that . Today, I have learned again Okhttp, Record the learning process on a blog , I hope it will help the readers .
OkHttp It's by the great name Square company-developed , This company has contributed a lot to the cause of open source , except OkHttp outside , And developed something like Picasso,Retrofit And other famous open source projects .OkHttp Not only is it easy to do on interface encapsulation , Even in the underlying implementation, it's a school of its own , Compared with the original HttpURLConnection, It can be said that there are too many , Now it has become a vast Android Developer's preferred network communication library .
OkHttp It's an efficient HTTP client , It has the following default features :
When there's a problem with the Internet OkHttp Still stick to your duty , It will automatically recover general connection problems , If you have more than one service IP Address , When the first one IP When the request fails ,OkHttp Will alternate between trying your configuration of other IP,OkHttp Use modern TLS technology (SNI, ALPN) Initializing a new connection , When the handshake fails, it will go back to TLS 1.0.
OkHttp Support Android 2.3 And above Android platform , as well as Java,JDK 1.7 And above .
OkHttp The use of is very simple . Its request / Respond to API Use Constructor mode builders To design , It supports blocking Synchronization request And with callback Asynchronous requests .
In order to better demonstrate OkHttp, Only synchronization is shown here / Asynchronous execution get/post The relevance of the request api, As for OkHttp Related calls to , Suggestions for reference OkHttp Official documents of :OkHttp Official website , No need to turn over the wall
About use post Request to send flow / file / Forms etc. , These functions need to be combined with another framework :OkIo, It will be shown in the next blog .
Don't talk much , Let's start using OkHttp Well .
It's the integration link that we love , We just need to modify it module Under the build.gradle, Join in OkHttp Dependence , The code is as follows :
implementation("com.squareup.okhttp3:okhttp:4.6.0")
Remember again Sync once , Make sure OkHttp Integrated into your project . When the author wrote this blog OkHttp3 Stable version number to achieve 4.6.0
, If the reader is in OkHttp An updated version of , Remember to update in time , Keep pace with the times .
Now that you've integrated OkHttp, It is necessary to carry out network related operations . In that case , You need to declare the network permissions under the manifest file , namely :
<uses-permission android:name="android.permission.INTERNET" />
in addition : If your Android Version is Android P( namely targetSdkVersion 27), Errors about the network may be reported when running the project , As shown in the figure :
reason : stay Android P On the equipment of the system , If the application uses unencrypted plaintext traffic http Network request , This will cause the application to be unable to make network requests ,https Will not be affected , In the same way, if the application uses WebView Load web page Then loading the web page also needs to be https request .
resolvent :
Three methods are also available , Here is the third solution , To broaden the solution
network_config( The name is not fixed ) Of xml
, The code is as follows :<network-security-config>
<base-config cleartextTrafficPermitted="true" />
</network-security-config>
android:networkSecurityConfig
attribute , The code is as follows : <application
...
android:networkSecurityConfig="@xml/network_security_config"
...
/>
Next , Let's go straight to layout the document activity_main.xml Compiling . The layout is simple , There are only four buttons , The code is as follows :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:orientation="vertical">
<Button
android:id="@+id/btn_get_syn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text=" send out get request —— Sync "/>
<Button
android:id="@+id/btn_get_asy"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text=" send out get request —— asynchronous "/>
<Button
android:id="@+id/btn_post_syn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text=" send out post request —— asynchronous "/>
<Button
android:id="@+id/btn_post_asy"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text=" send out post request —— asynchronous "/>
</LinearLayout>
after , Let's simply encapsulate the requested URL, namely http://wwww.baidu.com
. It is suggested that you want to go deep OkHttp Of the readers themselves build a Tomcat/Apache The server , Upload the resource file to the server , Then visit the local path , This can deepen the understanding of network requests . Here in order to facilitate the demonstration of the direct network request Baidu , The code is as follows :
private static final String URL = "http://wwww.baidu.com";
Sync GET The steps of the request are simple , It's mostly divided into :
call.execute()
Method to submit a synchronization request . Be careful , Because it's a synchronization request , So the api To put it in a child thread , Avoid blocking the main thread , cause ANR abnormal . in addition ,Android3.0 In the future, it is not allowed to access the network in the main thread .The code is as follows :
private void getBySynchronized() {
btn_get_syn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 1. structure Client object
OkHttpClient client = new OkHttpClient();
// 2. Build with builder mode and chain call Request object
final Request request = new Request.Builder()
.url(URL) // request URL
.get() // The default is get request , Don't write
.build();
// 3. adopt 1 and 2 Produced Client and Request Object to generate Call object
final Call call = client.newCall(request);
// 4. The synchronous get Request needs to use execute() Method , And in order to prevent the main thread from blocking, it needs to be placed in the sub thread itself
new Thread(new Runnable() {
@Override
public void run() {
try {
// 6. structure response object
Response response = call.execute();
Log.d(TAG, " The synchronous get The request is successful ! The requested information is :" + response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
});
}
asynchronous GET The first few steps of the request are the same as synchronization , Just the last one is through call.enqueue(Callback())
To submit a request , The code is as follows :
private void getByAsynchronized() {
btn_get_asy.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 1. structure Client object
OkHttpClient client = new OkHttpClient();
// 2. Build with builder mode and chain call Request object
final Request request = new Request.Builder()
.url(URL) // request URL
.get() // The default is get request , Don't write
.build();
// 3. adopt 1 and 2 Produced Client and Request Object to generate Call object
Call call = client.newCall(request);
// 4. call Call Object's enqueue() Method , And implement a callback implementation class
call.enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
Log.d(TAG, " Send asynchronously get request was aborted !");
e.printStackTrace();
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
Log.d(TAG, " Send asynchronously get The request is successful ! The requested information is :" + response.body().string());
}
});
}
});
}
Sync POST The requested steps are similar to synchronization GET request , It's mostly divided into :
call.execute()
Method to submit a synchronization request .The code is as follows :
private void postBySynchronized() {
btn_post_syn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 1. structure Client object
OkHttpClient client = new OkHttpClient();
// 2. Use builder mode and chain call to build key value pair object
FormBody formBody = new FormBody.Builder()
.add("username", "admin")
.add("password", "123456")
.build();
// 3. Build with builder mode and chain call Request object
final Request request = new Request.Builder()
.url(URL) // request URL
.post(formBody) // The default is get request , Don't write
.build();
// 4. adopt 1 and 3 Produced Client and Request Object to generate Call object
final Call call = client.newCall(request);
// 5. The synchronous post Request needs to use execute() Method , And in order to prevent the main thread from blocking, it needs to be placed in the sub thread itself
new Thread(new Runnable() {
@Override
public void run() {
try {
// 6. structure response object
Response response = call.execute();
Log.d(TAG, " The synchronous post The request is successful ! The requested information is :" + response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
});
}
asynchronous POST The first few steps of the request are the same as synchronization , Just the last one is through call.enqueue(Callback())
To submit a request , The code is as follows :
private void postByAsynchronized() {
btn_post_asy.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 1. structure Client object
OkHttpClient client = new OkHttpClient();
// 2. Use builder mode and chain call to build key value pair object
FormBody formBody = new FormBody.Builder()
.add("username", "admin")
.add("password", "123456")
.build();
// 3. Build with builder mode and chain call Request object
final Request request = new Request.Builder()
.url(URL) // request URL
.post(formBody) // The default is get request , Don't write
.build();
// 4. adopt 1 and 3 Produced Client and Request Object to generate Call object
Call call = client.newCall(request);
// 5. call Call Object's enqueue() Method , And implement a callback implementation class
call.enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
Log.d(TAG, " Send asynchronously post request was aborted !");
e.printStackTrace();
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
Log.d(TAG, " Send asynchronously post The request is successful ! The requested information is :" + response.body().string());
}
});
}
});
}
Generally speaking , Although synchronization / Asynchronous calls have their own advantages and disadvantages , In the actual project , We are still Asynchronous call It's going to be used a little bit more , collocation RxJava/RxAndroid as well as EventBus, Can enhance the user experience . Of course , If it's for rapid development, it's simpler demo, A synchronous invocation That's enough. .