Android App网络通信中通过okhttp调用HTTP接口讲解及实战(包括GET、表单格式POST、JSON格式POST 附源码)

news2024/9/20 9:06:15

需要全部源码或运行有问题请点赞关注收藏后评论区留言~~~

一、通过okhttp调用HTTP接口

尽管使用HttpURLConnection能够实现大多数的网络访问操作,但是操作过于繁琐,于是Andorid从9.0是使用okhttp这个框架

由于okhttp属于第三方框架  所以使用前要修改模块的build.gradle 增加下面一行依赖配置

implementation 'com.squareup.okhttp3:okhttp:4.9.1

当然访问网络之前需要先申请上网权限,也就是在AndroidManifest.xml中补充以下权限

<uses-permission android:name="android.permission.INTERNET"/>

 okhttp的网络访问功能非常强大,单就HTTP接口调用而言,它就支持三种访问方式。分别是GET方式的请求,表单格式的POST请求,JSON格式的POST请求 下面分别进行讲解以及实战

1:GET方式的请求

不管是GET还是POST方式 okhttp在访问网络时都要经历以下四个步骤

1:使用OkHttpClient类创建一个okhttp客户端对象

2:使用Request类创建一个GET或POST方式的请求结构

3:调用第一步骤中客户点对象的newCall方法 方法参数为第二步骤中的请求结构

4:调用第三步骤中Call对象的enquene方法,将本次请求加入HTTP访问的执行队列

综合以下四个步骤 接下来查询新浪网的证券板块的上证指数作为实战例子

读者可自行查询其他网址 进行替换即可

 

 

 2:表单格式的POST请求

对于okhttp来说,POST方式与GET方式的调用过程大同小异,主要区别在于如何创建请求结构,除了通过post方法表示本次请求采取POST方式外,还要给post方法填入请求参数

下面以登录功能为例,用户输入用户名和密码,App会把它们封装进FormBody结构后提交给后端服务器进行验证

当然首先你要确保后端服务器接口正常开启和运行~

 3:JSON格式的POST请求

由于表单格式不能传递复杂的数据,因此App在于服务端交互时经常使用JSON格式,设定好JSON串的字符编码后再放入RequestBody结构中

同样要确保服务器接口开启并且正常运行

 最后 全部代码如下

Java类

package com.example.network;

import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.RadioGroup;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;

import com.example.network.constant.NetConst;

import org.json.JSONObject;

import java.io.IOException;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

public class OkhttpCallActivity extends AppCompatActivity {
    private final static String TAG = "OkhttpCallActivity";
    private final static String URL_STOCK = "https://hq.sinajs.cn/list=s_sh000001";
    private final static String URL_LOGIN = NetConst.HTTP_PREFIX + "login";
    private LinearLayout ll_login; // 声明一个线性布局对象
    private EditText et_username; // 声明一个编辑框对象
    private EditText et_password; // 声明一个编辑框对象
    private TextView tv_result; // 声明一个文本视图对象
    private int mCheckedId = R.id.rb_get; // 当前选中的单选按钮资源编号

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_okhttp_call);
        ll_login = findViewById(R.id.ll_login);
        et_username = findViewById(R.id.et_username);
        et_password = findViewById(R.id.et_password);
        tv_result = findViewById(R.id.tv_result);
        RadioGroup rg_method = findViewById(R.id.rg_method);
        rg_method.setOnCheckedChangeListener((group, checkedId) -> {
            mCheckedId = checkedId;
            int visibility = mCheckedId == R.id.rb_get ? View.GONE : View.VISIBLE;
            ll_login.setVisibility(visibility);
        });
        findViewById(R.id.btn_send).setOnClickListener(v -> {
            if (mCheckedId == R.id.rb_get) {
                doGet(); // 发起GET方式的HTTP请求
            } else if (mCheckedId == R.id.rb_post_form) {
                postForm(); // 发起POST方式的HTTP请求(报文为表单格式)
            } else if (mCheckedId == R.id.rb_post_json) {
                postJson(); // 发起POST方式的HTTP请求(报文为JSON格式)
            }
        });
    }

    // 发起GET方式的HTTP请求
    private void doGet() {
        OkHttpClient client = new OkHttpClient(); // 创建一个okhttp客户端对象
        // 创建一个GET方式的请求结构
        Request request = new Request.Builder()
                //.get() // 因为OkHttp默认采用get方式,所以这里可以不调get方法
                .header("Accept-Language", "zh-CN") // 给http请求添加头部信息
                .url(URL_STOCK) // 指定http请求的调用地址
                .build();
        Call call = client.newCall(request); // 根据请求结构创建调用对象
        // 加入HTTP请求队列。异步调用,并设置接口应答的回调方法
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) { // 请求失败
                // 回到主线程操纵界面
                runOnUiThread(() -> tv_result.setText("调用股指接口报错:"+e.getMessage()));
            }

            @Override
            public void onResponse(Call call, final Response response) throws IOException { // 请求成功
                String resp = response.body().string();
                // 回到主线程操纵界面
                runOnUiThread(() -> tv_result.setText("调用股指接口返回:\n"+resp));
            }
        });
    }

    // 发起POST方式的HTTP请求(报文为表单格式)
    private void postForm() {
        String username = et_username.getText().toString();
        String password = et_password.getText().toString();
        // 创建一个表单对象
        FormBody body = new FormBody.Builder()
                .add("username", username)
                .add("password", password)
                .build();
        OkHttpClient client = new OkHttpClient(); // 创建一个okhttp客户端对象
        // 创建一个POST方式的请求结构
        Request request = new Request.Builder().post(body).url(URL_LOGIN).build();
        Call call = client.newCall(request); // 根据请求结构创建调用对象
        // 加入HTTP请求队列。异步调用,并设置接口应答的回调方法
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) { // 请求失败
                // 回到主线程操纵界面
                runOnUiThread(() -> tv_result.setText("调用登录接口报错:"+e.getMessage()));
            }

            @Override
            public void onResponse(Call call, final Response response) throws IOException { // 请求成功
                String resp = response.body().string();
                // 回到主线程操纵界面
                runOnUiThread(() -> tv_result.setText("调用登录接口返回:\n"+resp));
            }
        });
    }

    // 发起POST方式的HTTP请求(报文为JSON格式)
    private void postJson() {
        String username = et_username.getText().toString();
        String password = et_password.getText().toString();
        String jsonString = "";
        try {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("username", username);
            jsonObject.put("password", password);
            jsonString = jsonObject.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 创建一个POST方式的请求结构
        RequestBody body = RequestBody.create(jsonString, MediaType.parse("text/plain;charset=utf-8"));
        OkHttpClient client = new OkHttpClient(); // 创建一个okhttp客户端对象
        Request request = new Request.Builder().post(body).url(URL_LOGIN).build();
        Call call = client.newCall(request); // 根据请求结构创建调用对象
        // 加入HTTP请求队列。异步调用,并设置接口应答的回调方法
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) { // 请求失败
                // 回到主线程操纵界面
                runOnUiThread(() -> tv_result.setText("调用登录接口报错:"+e.getMessage()));
            }

            @Override
            public void onResponse(Call call, final Response response) throws IOException { // 请求成功.setText("调用登录接口返回:\n"+resp));
            }
        });
    }

}

XML文件

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <RadioGroup
        android:id="@+id/rg_method"
        android:layout_width="match_parent"
        android:layout_height="30dp"
        android:orientation="horizontal">

        <RadioButton
            android:id="@+id/rb_get"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:checked="true"
            android:gravity="left|center"
            android:text="GET方式"
            android:textColor="@color/black"
            android:textSize="16sp" />

        <RadioButton
            android:id="@+id/rb_post_form"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:checked="false"
            android:gravity="left|center"
            android:text="表单POST"
            android:textColor="@color/black"
            android:textSize="16sp" />

        <RadioButton
            android:id="@+id/rb_post_json"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:checked="false"
            android:gravity="left|center"
            android:text="JSON POST"
            android:textColor="@color/black"
            android:textSize="16sp" />
    </RadioGroup>

    <LinearLayout
        android:id="@+id/ll_login"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingLeft="5dp"
        android:paddingRight="5dp"
        android:orientation="vertical"
        android:visibility="gone">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="40dp"
            android:orientation="horizontal">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:gravity="center"
                android:text="用户名:"
                android:textColor="@color/black"
                android:textSize="17sp" />

            <EditText
                android:id="@+id/et_username"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="@drawable/editext_selector"
                android:gravity="left|center"
                android:hint="请输入用户名"
                android:maxLength="11"
                android:textColor="@color/black"
                android:textSize="17sp" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="40dp"
            android:layout_marginTop="10dp"
            android:orientation="horizontal">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:gravity="center"
                android:text="密 码:"
                android:textColor="@color/black"
                android:textSize="17sp" />

            <EditText
                android:id="@+id/et_password"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="@drawable/editext_selector"
                android:gravity="left|center"
                android:hint="请输入密码"
                android:inputType="numberPassword"
                android:maxLength="6"
                android:textColor="@color/black"
                android:textSize="17sp" />

        </LinearLayout>

    </LinearLayout>

    <Button
        android:id="@+id/btn_send"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="发起接口调用"
        android:textColor="@color/black"
        android:textSize="17sp" />

    <TextView
        android:id="@+id/tv_result"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingLeft="5dp"
        android:textColor="@color/black"
        android:textSize="17sp" />
</LinearLayout>

创作不易 觉得有帮助请点赞关注收藏~~~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/31283.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

我们的程序是如何跑起来的?

1.我们写的代码写完并测试以后是如何部署给用户使用的? 1. 准备所需要的服务器 2. 在服务器上安装JDK、mysql、redis、Tomcat、Nginx等环境 3. 进行mysql、redis、nginx的连接配置 4. 项目打包。前端构建打包成功后在根目录dist文件夹中&#xff1b;后端打成jar包&#xff0c…

基于改进海洋捕食者算法求解单目标优化问题附matlab代码(NMPA)

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;修心和技术同步精进&#xff0c;matlab项目合作可私信。 &#x1f34e;个人主页&#xff1a;Matlab科研工作室 &#x1f34a;个人信条&#xff1a;格物致知。 更多Matlab仿真内容点击&#x1f447; 智能优化算法 …

VLAN网络支持ipv6的交换机和虚机配置

VLAN支持ipv6的交换机和虚机配置前言一、创建VLAN网络并配置交换机1.规划并在OpenStack上创建 VLAN网络2.在交换机上配置VLAN二、Ubuntu虚机配置1.创建虚机2.在OpenStack上查看port3.登录虚机配置网卡3.1登录虚机后&#xff0c;发现虚机没获取到openstack上对应port的ipv6地址。…

Qt编写跨平台视频监控系统(64通道占用7%CPU/支持win_linux_mac等)

一、前言 视频监控组件经历过数十年的迭代&#xff0c;从最初的只简单播放个rtsp视频流&#xff0c;到现在支持各种音频视频文件格式&#xff08;mp3、wav、mp4、asf、rm、rmvb、mkv等&#xff09;、支持各种视频流格式&#xff08;rtp、rtsp、rtmp、http等&#xff09;、支持…

10个JavaScript常见高级知识点

今天&#xff0c;给大家分享的是一篇干货知识《10个JavaScript常见高级知识点》&#xff0c;主要针对初级前端和想要面试找工作的同学&#xff0c;想要学好前端&#xff0c;除了要掌握JavaScript的基础知识外&#xff0c;还需要掌握一些高级的知识点。 学会了下面这些常见的高…

鼠标经过图片在边框内放大动效

鼠标没有经过&#xff1a; 鼠标经过的时候&#xff0c;看图&#xff0c;应该可以看出变化吧&#xff01;图有放大的效果。 样式&#xff1a;图片由一个盒子包着&#xff0c;盒子加上overflow:hidden的样式&#xff0c;即可以保证图片在边框内放大。 然后给图片加上动画效果就可…

JavaWeb开发之——数据库设计(20)

一 概述 数据库设计-简介数据库设计-多表关系实现数据库设计-案例 二 数据库设计-简介 2.1 软件的研发步骤 2.2 数据库设计概念 数据库设计就是根据业务系统的具体需求&#xff0c;结合我们所选用的DBMS(Database Management System-数据库管理系统)&#xff0c;为这个业务系…

运动哪种耳机好用,推荐五款适合运动的耳机分享

​经常佩戴耳机的小伙伴都知晓传统的蓝牙耳机相对于有线耳机来说比较方便&#xff0c;但也存在着耳道一直堵塞导致细菌的滋生等因素的存在&#xff0c;但在近些年火热的骨传导耳机却能够将这些问题一一化解&#xff0c;基本可以说是百利而无一害&#xff0c;所以今天我就给小伙…

第一章 计算机系统体系结构

1.1 什么是计算机体系结构 本章的第一个概念是计算机系统(computer system)。 计算机系统包括读取并执行程序的 中央处理单元(CPU&#xff0c; 保存程序和数据的存储器以及将芯片转换为实用系统的 其他子系统。 这些子系统会使CPU与显示器、打印机、Internet等外部设备之间的…

【优化求解】整数规划求解机票超售优化赔付问题【含Matlab源码 2182期】

⛄一、问题 A航空公司每天有6班航班从上海到北京&#xff0c;从上午10点到晚上8点&#xff0c;每两小时发一班航班。某天获知&#xff0c;前三班机每班可以容纳100名旅客&#xff0c;后三班机每班可以容纳150名旅客。如果某次航班超售&#xff0c;A航空公司可以把某预定了该次…

【JSP/Servlet】基于WEB的通讯录系统

巩固JSP/Servlet系统开发描述步骤系统功能描述一、创建一个登录页面二、模拟数据&#xff08;用数据库模拟用户名和密码还有用户的通讯录&#xff09;三、创建一个JDBC工具类四、判断在登录页面输入的用户名和密码是否正确五、利用cookie实现保存六、以表格形式显示出我的通讯录…

2022最新MySQL面试题-有详细完整的答案解析

MySQL专题面试题 MySQL中有哪些存储引擎&#xff1f; InnoDB存储引擎 InnoDB是MySQL的默认事务型引擎&#xff0c;也是最重要、使用最广泛的存储引擎。它被设计用来处理大量的短期(short-lived)事务&#xff0c;应该优先考虑InnoDB引擎。 MylSAM存储引擎 在MySQL 5.1及之前的…

操作简单的BI数据分析软件有哪些?实际体验如何?

使用者没有IT基础&#xff0c;不懂代码&#xff0c;又需要对大量复杂的数据进行深度分析&#xff1b;分析效率要高&#xff1b;报表要直观易理解&#xff1b;最好能让每个浏览者都自己动手做分析。现在市面上&#xff0c;能够满足这些要求的BI数据分析软件有哪些&#xff1f;实…

一文速通MybatisPlus

目录 Mybatis-plus简介 MP特性 框架的结构 MP快速入门 配置日志输出 主键生成策略 自动填充 方式一&#xff1a;数据库级别 方式二&#xff1a;代码控制级别(常用) 乐观锁和悲观锁 测试乐观锁单线程成功的例子 乐观锁多线程失败案例 查询操作 分页查询 删除操作 删除…

C++ 手动实现单向循环链表(课后作业版)

单向循环链表&#xff0c;并实现增删查改等功能 首先定义节点类&#xff0c;类成员包含当前节点的值&#xff0c; 指向下一个节点的指针 循环链表的尾节点指向头节点 节点定义&#xff1a; //node definition template <typename T> class Node { public:T value;Nod…

Vue的生命周期快速入门

图示 流程 new Vue()实例化一个vue实例&#xff0c;然后init初始化event 和 lifecycle&#xff0c; 其实这个过程中分别调用了3个初始化函数&#xff08;initLifecycle(), initEvents(), initRender()&#xff09;&#xff0c;分别初始化了生命周期&#xff0c;事件以及定义cr…

k8s 资源管理及查看命令

关注 迪答数据 公众号获取更多 技术/数据 干货文章 文章传送门&#xff1a;数据治理之指标体系管理 管理容器的计算资源 参考文档&#xff1a; Kubernetes Managing Compute Resources for Containers(opens new window)https://kubernetes.io/docs/concepts/configuration/m…

go slice 扩容机制

前言 go语言没有ArrayList这样的封装&#xff0c;但是官方原生提供slice&#xff0c;底层就是数组存储&#xff0c;并且能自动扩容&#xff0c;相较于ArrayList的默认10&#xff0c;扩容5&#xff0c;slice的逻辑是有区别的。slice默认容量0。 demo go版本号 huahuaMac-min…

第一章 数据库绪论

数据库绪论 数据管理的三个阶段 人工管理阶段 文件系统阶段 数据库系统阶段 基本术语 数据&#xff08;Data&#xff09; 计算机用来描述事物的记录&#xff08;文字&#xff0e;图形&#xff0e;图像&#xff0e;声音&#xff09;数据的形式本身并不能完全表达其内容&a…

Transformer Fusion for Indoor RGB-D Semantic Segmentation

如何聚合多尺度特征这是一个问题&#xff0c;现有的方法大多通过卷积来实现&#xff0c;而很少在特征融合的地方使用长距离依赖&#xff0c;因此对于大物体的分割就会有挑战。本文提出基于transformer的融合策略&#xff0c;来更好的建模上下文。 TransD-Fusion包含①&#xff…