【Android】OkHttp发起GET请求 && POST请求


三三要成为安卓糕手

一:OkHttp介绍

OkHttp 是一个开源的、强大且高效的 HTTP 客户端库,主要用于在 Java后端和Android 项目中进行网络请求。

java 复制代码
//在gradle中添加依赖
com.squareup.okhttp3:okhttp:4.12.0

二:GET请求

java 复制代码
  /**
     * 使用OkHttp发起get请求
     */
    private void  sendGetRequest(){
        String id = etUserId.getText().toString();
        String urlAddress = "http://titok.fzqq.fun/addons/cms/api.user/userInfo?user_id=" + id + "&type=archives";
        //创建OkHttpClient实例对象,用于发起请求
        OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .connectTimeout(10,TimeUnit.SECONDS)
                .readTimeout(30, TimeUnit.SECONDS)
                .build();

        //设置请求属性,比如地址,方法属性
        Request request = new Request.Builder()
                .url(urlAddress)
                .get()
                .build();

        //发起单个请求
        Call call = okHttpClient.newCall(request);

        //接收响应
        Callback callback = new Callback() {
            @Override
            public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        if(response.isSuccessful()){
                            //响应成功
                            try {
                                String result = response.body().string();
                                Log.i(TAG, "run: result" + result);
                                //把json字符串转化为对象
                                UserInfoQuery userInfoQuery = new Gson().fromJson(result, UserInfoQuery.class);
                                String msg = "当前的用户名是:" + userInfoQuery.getData().getUser().getNickname();
                                Toast.makeText(OkHttpActivity.this,msg,Toast.LENGTH_SHORT).show();
                            } catch (IOException e) {
                                throw new RuntimeException(e);
                            }

                        }else{
                            Toast.makeText(OkHttpActivity.this,"网络请求失败"+response.code()
                                    ,Toast.LENGTH_SHORT).show();
                        }
                    }
                });
            }

            @Override
            public void onFailure(@NonNull Call call, @NonNull IOException e) {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(OkHttpActivity.this,"网络请求失败",Toast.LENGTH_SHORT).show();
                    }
                });
            }
        };
        call.enqueue(callback);
    }

1:大致步骤

  • 使用builder去创建OkHttpClient实例对象,设置一些连接的属性:常见连接超时,数据读取超时
  • 使用builder设置请求属性:常见url,get方法
  • 调用newCall发起单次请求,传入request参数,使用enqueue异步线程
  • new Callback();重写接口中的onResponse方法和onFailure方法
  • 方法中的内部逻辑,对于ui的处理要在主线程中进行,调用runOnUiThread(new Runnable接口,重写run方法)

2:一些细节

  • 我们一般不会直接new一个request,而是选择一个底下的一个builder的东西

(1)内部回调接口

在 OkHttp 中,call.enqueue(callback) 并非 "把响应丢进 call 里",而是通过回调机制实现异步请求的结果处理

  • Call 对象是对一个 HTTP 请求的封装,调用 enqueue(callback) 时,其实是向Call 注册了一个回调接口
  • OkHttp 会在后台线程执行网络请求,当请求完成(成功或失败)后,会自动调用onResponseonFailure方法,并将响应结果(Response 对象)作为参数传入。

(2)次线程转主线程

接口中重写的onResponse方法和onFailure方法内部的代码,涉及到UI应该要回到主线程中去进行

回到主线程去完成ui(弹窗操作)

(3)enqueue方法的说明

"enqueue" 把...... 加入队列

在 Java 中,enqueue 方法的签名是 void enqueue(Callback responseCallback) ,它接收一个 Callback 类型的参数,Callback 是 OkHttp 中定义的一个接口,包含两个抽象方法:

  • onResponse(Call call, Response response):当 HTTP 请求成功完成,且服务器返回了响应时,该方法会被调用,response 参数包含了从服务器获取到的响应信息,比如响应码、响应头、响应体等;call 参数则是当前正在处理结果的这个请求对应的 Call 对象。
  • onFailure(Call call, IOException e):当请求执行过程中发生错误,比如网络连接失败、超时等情况,这个方法会被调用。

(4)response.body().string()

主要作用是将 ResponseBody 的内容以字符串形式读取出来。

它会根据响应体的编码(Content-Type ),把响应体中的字节数据解码为字符串。并非用toString方法

(5)toString () 方法

默认的 toString() 方法返回的是 ResponseBody 类的名称以及对象的哈希码等信息,而不是响应体中的实际内容

例如:可能返回类似 okhttp3.ResponseBody@12345678 这样的字符串,其中 okhttp3.ResponseBody 是类名,@12345678 是对象的哈希码表示 。

(6)TimeUnit 时间单位

在设置超时方面,可以用安卓内部定义好的时间的单位常量

3:效果

三:POST请求

java 复制代码
/**
     * POST请求
     */
    private void sendPostRequest(){
        String loginUrl = "http://titok.fzqq.fun/addons/cms/api.login/login";
        OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .connectTimeout(10,TimeUnit.SECONDS)
                .readTimeout(30,TimeUnit.SECONDS)
                .build();

        String account = etUserName.getText().toString();
        String password = etPassword.getText().toString();


        //用Gson去拼接一个请求体
        String jsonBody = new Gson().toJson(new ReqLogin(account, password));

        //请求体的数据格式是Json,编码格式是utf-8
        MediaType mediaType = MediaType.get("application/json;charset=utf-8");
        RequestBody requestBody = RequestBody.create(jsonBody, mediaType);

        //构建请求
        Request request = new Request.Builder()
                .url(loginUrl)
                .post(requestBody)
                .build();

        //发起请求
        Call call = okHttpClient.newCall(request);

        Callback callback = new Callback() {
            @Override
            public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        if(response.isSuccessful()){
                            try {
                                String json = response.body().string();
                                Log.i(TAG, "run: " + json);
                                
                                //把json数据转化为对象,获取其中的属性
                                ResLogin resLogin = new Gson().fromJson(json, ResLogin.class);
                                String msg = resLogin.getMsg();
                                int userId = resLogin.getData().getUser_id();
                                Toast.makeText(OkHttpActivity.this,msg + ".欢迎用户" + userId
                                        , Toast.LENGTH_SHORT).show();
                                
                            } catch (IOException e) {
                                throw new RuntimeException(e);
                            }
                        }else {
                            Toast.makeText(OkHttpActivity.this,"登录失败",Toast.LENGTH_SHORT).show();
                        }
                    }
                });
            }

            @Override
            public void onFailure(@NonNull Call call, @NonNull IOException e) {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(OkHttpActivity.this
                                ,"POST登录请求失败",Toast.LENGTH_SHORT).show();
                    }
                });
            }
        };

        call.enqueue(callback);


    }

1:流程

  • 设置连接属性
  • ui上获取数据,Gson.toJson拼接字符串请求体
  • 设置请求体数据格式
  • 构建请求
  • 发起请求
  • 处理响应

2:一些细节

(1) 设计body参数

(2)MediaType.get("application/json;charset=utf-8");

媒体类型

用于定义请求体或响应体的数据格式和编码方式,是处理 JSON 数据时的常见用法。

3:登录效果

四:快捷生成JSON对应的对象

商业场景中是会创建一个实体类对象的;而非进行字符串拼接

java 复制代码
//先用日志获取json体
String json = response.body().string();
Log.i(TAG, "run: " + json);


//在依据日志生成java对象,通过对象去获取其中的属性
new Gson().fromJson(json, ResLogin.class)
java 复制代码
package com.xlong.networkbyjavaproject.bean;

public class ResLogin {

    /**
     * code : 1
     * msg : 登录成功
     * time : 1756263107
     * data : {"token":"6c45ff48-c7ef-4666-918e-26dabb214746","user_id":4}
     */

    private int code;
    private String msg;
    private String time;
    private DataBean data;

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public String getTime() {
        return time;
    }

    public void setTime(String time) {
        this.time = time;
    }

    public DataBean getData() {
        return data;
    }

    public void setData(DataBean data) {
        this.data = data;
    }

    public static class DataBean {
        /**
         * token : 6c45ff48-c7ef-4666-918e-26dabb214746
         * user_id : 4
         */

        private String token;
        private int user_id;

        public String getToken() {
            return token;
        }

        public void setToken(String token) {
            this.token = token;
        }

        public int getUser_id() {
            return user_id;
        }

        public void setUser_id(int user_id) {
            this.user_id = user_id;
        }
    }
}
相关推荐
兩尛1 分钟前
Spring面试
java·spring·面试
Java中文社群8 分钟前
服务器被攻击!原因竟然是他?真没想到...
java·后端
Full Stack Developme20 分钟前
java.nio 包详解
java·python·nio
零千叶36 分钟前
【面试】Java JVM 调优面试手册
java·开发语言·jvm
代码充电宝1 小时前
LeetCode 算法题【简单】290. 单词规律
java·算法·leetcode·职场和发展·哈希表
li3714908901 小时前
nginx报400bad request 请求头过大异常处理
java·运维·nginx
摇滚侠1 小时前
Spring Boot 项目, idea 控制台日志设置彩色
java·spring boot·intellij-idea
Jeled2 小时前
Retrofit 与 OkHttp 全面解析与实战使用(含封装示例)
android·okhttp·android studio·retrofit
Aevget2 小时前
「Java EE开发指南」用MyEclipse开发的EJB开发工具(二)
java·ide·java-ee·eclipse·myeclipse
黄昏晓x2 小时前
C++----多态
java·jvm·c++