欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【Android】OKHTTP使用

程序员文章站 2022-03-07 09:32:26
...

如果饿了就吃,困了就睡,渴了就喝,人生就太无趣了
参考博客: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

【Android】OKHTTP使用

目录结构如图2

【Android】OKHTTP使用

2.2.2 更改AndroidManifest.xml文件

AndroidManifest.xml文件中引用刚刚增加的xml文件

android:networkSecurityConfig="@xml/network_security_config"

3.后台接口

后台接口使用SpringBoot开启了一个web服务,有两个接口,分别测试GETPOST方法。

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按钮,会获取AccountPassWord输入框的值,作为/android/postTest/接口的传送数据。

【Android】OKHTTP使用

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,说明会有两个子线程会发来消息,就是后面调用的postget方法的子线程。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();
    }

可以看出发送消息的主要代码就是下面这三行:

  • 通过已经实例化的handlerobtainMessage()方法实例化Message对象。参数是Message.what的值。
  • 将传送的数据赋值给Messageobj变量。
  • 最后调用sendMessage()方法发送消息
	Message message = handler.obtainMessage(2);
	message.obj = data;
	handler.sendMessage(message);

6.3 Message介绍

通过上面的说明,已经了解Message对象就是线程之间通信的对象,贴出部分声明变量的源码:

  • what就是标记作用,用来区分不同的Message
  • arg1arg2是用来存放需要传递的整数值
  • 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();
    }
}