android网络框架之OKhttp一个处理网络请求的开源项目,是安卓端最火热的轻量级框架,适用于 JVM、Android 和 GraalVM 的细致 HTTP 客户端。
GitHub开源地址:https://github.com/square/okhttp
一、引用第三方包okhttp
1、在模块的build.gradle文件中加入:
dependencies {
implementation 'com.squareup.okhttp3:okhttp:4.12.0'
}
2、点击File->Sync Project with Gradle Files
3、在AndroidManifest.xml文件中加入:
<uses-permission android:name="android.permission.INTERNET" />
作用:使项目可以连接网络,默认是不允许访问网络的
在节点application中加入属性android:usesCleartextTraffic="true",以允许发送http请求,默认只允许发送https请求。
结果如图所示:
二、okhttp的使用
1、发送get请求
get请求分同步和异步两种方式。
(1)发送同步get请求
package com.example.myapplication;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import java.io.IOException;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class MainActivity extends AppCompatActivity {
private TextView tv1;
private Handler handler=new Handler(Looper.getMainLooper());
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv1 = findViewById(R.id.tv1);
findViewById(R.id.btn1).setOnClickListener(v->{
new Thread(){
@Override
public void run() {
super.run();
OkHttpClient client=new OkHttpClient();
Request request= new Request.Builder().url("https://www.baidu.com").build(); //或new Request.Builder().url("https://www.baidu.com").get().build();
try {
Response response=client.newCall(request).execute();//execute()为同步请求
String data=response.body().string();
//陌生线程不能直接访问UI线程的,所以要使用handler.post()
handler.post(new Runnable() {
@Override
public void run() {
tv1.setText(data);
}
});
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}.start();
});
}
}
用lambda表达式:
new Thread(()->{
OkHttpClient client=new OkHttpClient();
Request request=new Request.Builder().url("https://www.baidu.com").build();
try {
Response response=client.newCall(request).execute();
String data=response.body().string();
handler.post(()->{
tv1.setText(data);
});
} catch (IOException e) {
throw new RuntimeException(e);
}
}).start();
(2)发送异步get请求
findViewById(R.id.btn1).setOnClickListener(v -> {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url("https://www.baidu.com").build(); //或new Request.Builder().url("https://www.baidu.com").get().build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(@NonNull Call call, @NonNull IOException e) {
}
@Override
public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
String data = response.body().string();
handler.post(()->{
tv1.setText(data);
});
}
});
});
同步用execute(),须手动创建线程;异步用enqueue(),会自动创建线程。
response.body().string()只能调用一次,在第一次时有返回值,第二次再调用时将会返回null。
response.body().string()要放在子线程中。
(3)传递参数
①以查询字符串形式传递参数,如http://124.93.196.45:10091/Neusoft/community/api/adv/list?title=开屏广告2&status=1
②构建HttpUrl.Builder对象
HttpUrl.Builder url=HttpUrl.parse("http://124.93.196.45:10091/Neusoft/community/api/adv/list").newBuilder();
url.addQueryParameter("title","开屏广告2");
url.addQueryParameter("status", "1");
Request request=new Request.Builder().url(url.build()).build();
2、发送post请求
post请求也分同步和异步两种方式,同步与异步的区别和get方法类似,这里只讲发送post异步请求的使用方法。
(1)post发送普通表单数据
String url = "https://example.com.cn/logincheck.php"; FormBody body=new FormBody.Builder() //FormBody继承自RequestBody .add("UNAME","") .add("PASSWORD", "") .add("CAPTCHA", "") .build();
OkHttpClient client=new OkHttpClient();
Request request=new Request.Builder().url(url).post(body).build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(@NonNull Call call, @NonNull IOException e) {
}
@Override
public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
if(response.isSuccessful()) {
String data=response.body().string();
handler.post(()->{
tv1.setText(data);
});
}
}
});
内容类型自动为:application/x-www-form-urlencoded。
(2)post发送含文件的表单数据
String url = "http://124.93.196.45:10091/Neusoft/times-model" + "/appUser/updatePersonaInfo";
File file = new File("/sdcard/ava.png");
RequestBody filebody = RequestBody.create(file, MediaType.parse("images/png"));
MultipartBody body = new MultipartBody.Builder() //MultipartBody继承自RequestBody
.setType(MultipartBody.FORM)
.addFormDataPart("name", "abcd")
.addFormDataPart("sex", "2")
.addFormDataPart("email", "2632422@qq.com")
.addFormDataPart("avatarfile", file.getName(), filebody)
.build();
Request request = new Request.Builder().url(url).post(body).header("Authorization", token).build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(@NonNull Call call, @NonNull IOException e) {
……
}
@Override
public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
if (response.isSuccessful()) {
String data = response.body().string();
……
}
}
});
内容类型自动为:multipart/form-data。
默认情况下不允许访问存储卡,若要允许访问存储卡,则需要以下两步:
①在AndroidManifest.xml文件中加入
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
if(ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED){ //判断是否有相关权限
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},1); //请求相关权限
}else{
……
}
String url = "http://example.com.cn/upload";
File file = new File("/sdcard/ava.png");
RequestBody body = RequestBody.create(file, MediaType.parse("application/octet-stream"));
Request request = new Request.Builder().url(url).post(body).build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(@NonNull Call call, @NonNull IOException e) {
……
}
@Override
public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
if (response.isSuccessful()) {
String data = response.body().string();
……
}
}
});
String url = "http://124.93.196.45:10091/Neusoft/community" + "/api/login";
String json="{\"username\":\"\",\"password\":\"\"}"; //json字符串
RequestBody body=RequestBody.create(json,MediaType.parse("application/json;charset=utf-8"));
OkHttpClient client=new OkHttpClient();
Request request=new Request.Builder().url(url).post(body).build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(@NonNull Call call, @NonNull IOException e) {
}
@Override
public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
if(response.isSuccessful()) {
String data=response.body().string();
handler.post(()->{
tv1.setText(data);
});
}
}
});
(5)post发送无参数请求
String url = "http://example.com.cn/post";
OkHttpClient client=new OkHttpClient();
Request request=new Request.Builder().url(url).post(RequestBody.create("",null)).build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(@NonNull Call call, @NonNull IOException e) {
……
}
@Override
public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
if(response.isSuccessful()) {
String data=response.body().string();
……
}
}
});
3、发送请求头信息
4、处理返回的信息
可以使用第三方包gson(gson的github开源地址为:https://github.com/google/gson)在json字符串与对象之间进行转换。
要使用gson,则在模块的build.gradle文件中加入:
dependencies {
implementation 'com.google.code.gson:gson:2.11.0'
}
新建类:
public class User { private String username; private String password; public User(String name,String pass){ this.username=name; this.password=pass; } public String getUsername() { return username; } public String getPassword() { return password;} }
对象转换为json字符串:
User user=new User("", "");
String json=new Gson().toJson(user);
json字符串转换为对象:
String json="{\"username\":\"\",\"password\":\"\"}";
User user=new Gson().fromJson(json,User.class);