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

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

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

一、通过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>

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

相关文章
|
4天前
|
存储 SQL 安全
网络安全的盾牌:漏洞防护与加密技术的实战应用
【8月更文挑战第27天】在数字化浪潮中,信息安全成为保护个人隐私和企业资产的关键。本文深入探讨了网络安全的两大支柱——安全漏洞管理和数据加密技术,以及如何通过提升安全意识来构建坚固的防御体系。我们将从基础概念出发,逐步揭示网络攻击者如何利用安全漏洞进行入侵,介绍最新的加密算法和协议,并分享实用的安全实践技巧。最终,旨在为读者提供一套全面的网络安全解决方案,以应对日益复杂的网络威胁。
|
1天前
|
运维 安全 应用服务中间件
自动化运维的利器:Ansible入门与实战网络安全与信息安全:关于网络安全漏洞、加密技术、安全意识等方面的知识分享
【8月更文挑战第30天】在当今快速发展的IT时代,自动化运维已成为提升效率、减少错误的关键。本文将介绍Ansible,一种流行的自动化运维工具,通过简单易懂的语言和实际案例,带领读者从零开始掌握Ansible的使用。我们将一起探索如何利用Ansible简化日常的运维任务,实现快速部署和管理服务器,以及如何处理常见问题。无论你是运维新手还是希望提高工作效率的资深人士,这篇文章都将为你开启自动化运维的新篇章。
|
1天前
|
Java
【实战演练】JAVA网络编程高手养成记:URL与URLConnection的实战技巧,一学就会!
【实战演练】JAVA网络编程高手养成记:URL与URLConnection的实战技巧,一学就会!
11 3
|
2天前
|
Java API UED
【实战秘籍】Spring Boot开发者的福音:掌握网络防抖动,告别无效请求,提升用户体验!
【8月更文挑战第29天】网络防抖动技术能有效处理频繁触发的事件或请求,避免资源浪费,提升系统响应速度与用户体验。本文介绍如何在Spring Boot中实现防抖动,并提供代码示例。通过使用ScheduledExecutorService,可轻松实现延迟执行功能,确保仅在用户停止输入后才触发操作,大幅减少服务器负载。此外,还可利用`@Async`注解简化异步处理逻辑。防抖动是优化应用性能的关键策略,有助于打造高效稳定的软件系统。
12 2
|
10天前
|
数据采集 存储 前端开发
豆瓣评分9.0!Python3网络爬虫开发实战,堪称教学典范!
今天我们所处的时代是信息化时代,是数据驱动的人工智能时代。在人工智能、物联网时代,万物互联和物理世界的全面数字化使得人工智能可以基于这些数据产生优质的决策,从而对人类的生产生活产生巨大价值。 在这个以数据驱动为特征的时代,数据是最基础的。数据既可以通过研发产品获得,也可以通过爬虫采集公开数据获得,因此爬虫技术在这个快速发展的时代就显得尤为重要,高端爬虫人才的收人也在逐年提高。
|
18天前
|
机器学习/深度学习 PyTorch TensorFlow
【PyTorch】PyTorch深度学习框架实战(一):实现你的第一个DNN网络
【PyTorch】PyTorch深度学习框架实战(一):实现你的第一个DNN网络
54 1
|
4天前
|
负载均衡 中间件 Go
五分钟给你的 gRPC 服务加上 HTTP 接口
五分钟给你的 gRPC 服务加上 HTTP 接口
|
30天前
|
移动开发 网络协议 算法
(十)Netty进阶篇:漫谈网络粘包、半包问题、解码器与长连接、心跳机制实战
在前面关于《Netty入门篇》的文章中,咱们已经初步对Netty这个著名的网络框架有了认知,本章的目的则是承接上文,再对Netty中的一些进阶知识进行阐述,毕竟前面的内容中,仅阐述了一些Netty的核心组件,想要真正掌握Netty框架,对于它我们应该具备更为全面的认知。
|
12天前
|
安全 网络安全 网络架构
【揭秘】大佬如何玩转内网与外联单位互访?SNAT+DNAT实战揭秘,让你的网络畅通无阻!
【8月更文挑战第19天】内网与外联单位间的访问是企业网络的关键需求。通过SNAT和DNAT技术可巧妙解决此问题。SNAT修改源IP地址,隐藏内网真实身份;DNAT改变目的IP地址,实现外部对内网服务器的访问。
31 0
|
28天前
|
SQL 安全 网络安全
网络安全的盾牌与利剑:漏洞防护与加密实战
【8月更文挑战第3天】在数字世界的无垠战场上,网络安全是守护数据边疆的盾牌,而信息安全则是斩断威胁的利剑。本文将深入探讨网络防御的核心要素,从网络安全漏洞的识别、利用到防范策略,再到加密技术的应用和安全意识的培养。我们将以代码示例为依托,揭示保护网络空间的实用技巧和策略,旨在为读者提供一套全面的网络安全解决方案。
下一篇
云函数