【Android】OKHTTP使用
如果饿了就吃,困了就睡,渴了就喝,人生就太无趣了
参考博客:https://blog.csdn.net/wsq_tomato/article/details/80301851
Android源码地址:https://github.com/keer123456789/OkHttpExample.git
Springboot后台地址:https://github.com/keer123456789/OkHttpServer.git
1.安装依赖
本次使用的是OKHTTP
的3.4.1版本
// https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp
implementation group: 'com.squareup.okhttp3', name: 'okhttp', version: '3.4.1'
2.更改配置
2.1 增加权限
在AndroidManifest.xml
中增加下面两行权限
<manifest>
......
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
......
</manifest>
2.2 添加配置文件
2.2.1 增加xml文件
在资源文件夹res
中添加network_security_config.xml
(名字随意),内容如下
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true" />
</network-security-config>
如图1,创建注意选择xml
目录结构如图2
2.2.2 更改AndroidManifest.xml
文件
在AndroidManifest.xml
文件中引用刚刚增加的xml文件
android:networkSecurityConfig="@xml/network_security_config"
3.后台接口
后台接口使用SpringBoot
开启了一个web服务,有两个接口,分别测试GET
和POST
方法。
3.1 GET 接口
GET /android/getTest/{info}
返回:Get success
3.2 POST接口
POST /android/postTest/
Data example:
{
"name":"keer",
"pass":"123456"
}
返回:POST success
3.3 后台代码
/**
* @BelongsProject: okhttpserver
* @BelongsPackage: com.keer.okhttpserver.Controller
* @Author: keer
* @CreateTime: 2020-02-29 22:13
* @Description: android使用OkHttp后台接口
*/
@RestController()
@RequestMapping("/android")
public class Controller {
private Logger logger = LoggerFactory.getLogger(Controller.class);
@RequestMapping(value = "/getTest/{info}", method = RequestMethod.GET)
public String getMethod(@PathVariable String info) {
logger.info("接收到Get请求,传来的信息:" + info);
return "Get success";
}
@RequestMapping(value = "/postTest", method = RequestMethod.POST)
public String postMethod(@RequestBody Map map) {
logger.info("接收到POST请求,传来的信息:" + map.toString());
return "Post success!!!";
}
}
4.Android 中的Activity的XML文件
4.1 代码
<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:stretchColumns="1"
tools:context=".MainActivity">
<TableRow>
<TextView
android:layout_height="wrap_content"
android:text="Account:" />
<EditText
android:id="@+id/account"
android:layout_height="wrap_content"
android:hint="Input your account" />
</TableRow>
<TableRow>
<TextView
android:layout_height="wrap_content"
android:text="PassWord:" />
<EditText
android:id="@+id/password"
android:layout_height="wrap_content"
android:inputType="textPassword" />
</TableRow>
<Button
android:id="@+id/get"
style="@style/Widget.AppCompat.Button"
android:layout_width="125dp"
android:layout_height="wrap_content"
android:text="GET" />
<Button
android:id="@+id/post"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minWidth="32dp"
android:text="POST" />
</TableLayout>
4.2 图片展示
如图3,模拟登陆界面。
- 点击
GET
按钮,会获取Account
的输入框的值,作为/android/getTest/{info}
接口的info
参数; - 点击
POST
按钮,会获取Account
和PassWord
输入框的值,作为/android/postTest/
接口的传送数据。
5.OKHTTP使用方法
5.1 GET方法使用
/**
* @param info 接口中info值
* @return
*/
public String myGet(String info) {
OkHttpClient client = new OkHttpClient();
//构建请求,request中默认是get方法,所以将.get()删去也不要紧
Request request = new Request.Builder()
.url("http://192.168.0.101:8080/android/getTest/" + info)
//.get() //加上和删去都不要紧
.build();
Response response = null;
String responseData = null;
try {
response = client.newCall(request).execute();
responseData = response.body().string();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("成功接收到返回值" + responseData);
return responseData;
}
5.2 POST方法使用
public String myPost() throws Exception {
OkHttpClient client = new OkHttpClient();
//构建请求头
final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
//构建JSON数据,作为传送的数据
JSONObject jsonObject = new JSONObject();
jsonObject.put("name", "keer");
jsonObject.put("pass", "123456");
//构建RequestBody
RequestBody body = RequestBody.create(JSON, jsonObject.toString());//这里是需要是json字符串
//构建请求request
Request request = new Request.Builder()
.url("http://192.168.0.101:8080/android/postTest")
.post(body) //将RequestBody作为post方法的参数。
.build();
Response response = client.newCall(request).execute();
String res = response.body().string();
System.out.println(res);
return res;
}
6.主线程和子线程
本人Android小小白,也是看别人的讲解,加上自己的理解,这一部分如有说错,谅解,欢迎指正!!!
6.1 android网络请求
自从android4.0之后,网络请求需要开启线程
,原因:
- 为了避免导致UI卡顿的情况:比如在OnCreate 里面先进行网络请求然后还要加载布局 。
- 一般大型软件开发时,负责网络通信的,和对数据做处理的,往往是两个不同的模块
这样通过回调的方式,使代码的耦合性降低,更易于分块。
Android提供了一个消息传递的机制——Handler,来帮助线程之间的通信。
6.2 Handler使用介绍
6.2.1 主线程中创建Handler
在主线程中创建一个Handler
实例,,并重写handleMessage()
方法,该方法就是子线程动作完成后,需要主线程做的动作。可以看到线程中的通信是通过Message
对象实现的。该方法中使用了switch
,说明会有两个子线程会发来消息,就是后面调用的post
和get
方法的子线程。switch
中的两个动作分别使用Toast
对象显示子线程发来的信息。Message
对象会在后面介绍。
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what){
case 1:{
Toast.makeText(MainActivity.this, "Get方法成功接收到返回值" + msg.obj.toString(), Toast.LENGTH_SHORT).show();
}break;
case 2:{
Toast.makeText(MainActivity.this, "Post方法成功接收到返回值" + msg.obj.toString(), Toast.LENGTH_SHORT).show();
}break;
}
}
};
6.2.2 子线程中发送消息
① GET方法的子线程
private void getTest(final String name) {
new Thread(new Runnable() {
@Override
public void run() {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("http://192.168.0.101:8080/android/getTest/" + name)
.build();
Response response = null;
String responseData = null;
try {
response = client.newCall(request).execute();
responseData = response.body().string();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("成功接收到返回值" + responseData);
Message message = handler.obtainMessage(1);
message.obj = responseData;
handler.sendMessage(message);
}
}).start();
}
② POST方法子线程
private void postTest(final JSONObject map) {
new Thread(new Runnable() {
@Override
public void run() {
OkHttpClient client = new OkHttpClient();
final MediaType JSON = MediaType.parse("application/json; charset=utf-8");//发送json数据的固定写法
JSONObject jsonObject = new JSONObject();
RequestBody body = RequestBody.create(JSON, map.toString());//这里是需要是json字符串
Request request = new Request.Builder()
.url("http://192.168.0.101:8080/android/postTest")//用安卓虚拟器跑也不要用127.0.0.1
.post(body)
.build();
String res = null;
try {
Response response = client.newCall(request).execute();
res = response.body().string();
System.out.println(res);
Message message = handler.obtainMessage(2);
message.obj = res;
handler.sendMessage(message);
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
可以看出发送消息的主要代码就是下面这三行:
- 通过已经实例化的
handler
中obtainMessage()
方法实例化Message
对象。参数是Message.what
的值。 - 将传送的数据赋值给
Message
的obj
变量。 - 最后调用
sendMessage()
方法发送消息
Message message = handler.obtainMessage(2);
message.obj = data;
handler.sendMessage(message);
6.3 Message介绍
通过上面的说明,已经了解Message
对象就是线程之间通信的对象,贴出部分声明变量的源码:
-
what
就是标记作用,用来区分不同的Message
-
arg1
和arg2
是用来存放需要传递的整数值 -
org
传送子线程中的实例化的对象。
/**
* User-defined message code so that the recipient can identify
* what this message is about. Each {@link Handler} has its own name-space
* for message codes, so you do not need to worry about yours conflicting
* with other handlers.
*/
public int what;
/**
* arg1 and arg2 are lower-cost alternatives to using
* {@link #setData(Bundle) setData()} if you only need to store a
* few integer values.
*/
public int arg1;
/**
* arg1 and arg2 are lower-cost alternatives to using
* {@link #setData(Bundle) setData()} if you only need to store a
* few integer values.
*/
public int arg2;
/**
* An arbitrary object to send to the recipient. When using
* {@link Messenger} to send the message across processes this can only
* be non-null if it contains a Parcelable of a framework class (not one
* implemented by the application). For other data transfer use
* {@link #setData}.
*
* <p>Note that Parcelable objects here are not supported prior to
* the {@link android.os.Build.VERSION_CODES#FROYO} release.
*/
public Object obj;
6.4 全部代码
MainActivity.java
中的全部代码如下
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
public static final int SHOW_RESPONSE = 0;
private Button getbt;
private Button postbt;
private EditText accountEdit;
private EditText passwordEdit;
private Handler handler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
getbt = (Button) findViewById(R.id.get);
postbt = (Button) findViewById(R.id.post);
accountEdit = (EditText) findViewById(R.id.account);
passwordEdit = (EditText) findViewById(R.id.password);
getbt.setOnClickListener(this);
postbt.setOnClickListener(this);
handler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what){
case 1:{
Toast.makeText(MainActivity.this, "Get方法成功接收到返回值" + msg.obj.toString(), Toast.LENGTH_SHORT).show();
}break;
case 2:{
Toast.makeText(MainActivity.this, "Post方法成功接收到返回值" + msg.obj.toString(), Toast.LENGTH_SHORT).show();
}break;
}
}
};
}
@Override
public void onClick(View v) {
String name = accountEdit.getText().toString();
String pass = passwordEdit.getText().toString();
if (v.getId() == R.id.post) {
JSONObject j = new JSONObject();
try {
j.put("name", name);
j.put("pass", pass);
} catch (JSONException e) {
e.printStackTrace();
}
postTest(j);
} else if (v.getId() == R.id.get) {
getTest(name);
}
}
@Override
public void onPointerCaptureChanged(boolean hasCapture) {
}
/**
* 发送get请求
*
* @param name
*/
private void getTest(final String name) {
new Thread(new Runnable() {
@Override
public void run() {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("http://192.168.0.101:8080/android/getTest/" + name)
.build();
Response response = null;
String responseData = null;
try {
response = client.newCall(request).execute();
responseData = response.body().string();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("成功接收到返回值" + responseData);
Message message = handler.obtainMessage(1);
message.obj = responseData;
handler.sendMessage(message);
}
}).start();
}
/**
* 发送POST请求
*
* @param map
*/
private void postTest(final JSONObject map) {
new Thread(new Runnable() {
@Override
public void run() {
OkHttpClient client = new OkHttpClient();
final MediaType JSON = MediaType.parse("application/json; charset=utf-8");//发送json数据的固定写法
JSONObject jsonObject = new JSONObject();
RequestBody body = RequestBody.create(JSON, map.toString());//这里是需要是json字符串
Request request = new Request.Builder()
.url("http://192.168.0.101:8080/android/postTest")//用安卓虚拟器跑也不要用127.0.0.1
.post(body)
.build();
String res = null;
try {
Response response = client.newCall(request).execute();
res = response.body().string();
System.out.println(res);
Message message = handler.obtainMessage(2);
message.obj = res;
handler.sendMessage(message);
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
}