【Android】网络编程之OKHTTP与Retrofit框架

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
简介: 上一期我们实现了Android的网络编程,通过Java代码在子线程中请求数据,再通过Java代码解析json数据,因为对于较复杂的json数据,通过java代码需要逐层解析比较困难,所以我们又通过第三方框架GSON,使用它可以直接将字符串解析成对象,并且封装成为一个实体类,配合实体类插件GsonFormatPlus,让我们只需通过简单的几行代码就实现数据解析


1. 上期回顾

上一期我们实现了Android的网络编程,通过Java代码在子线程中请求数据,再通过Java代码解析json数据,因为对于较复杂的json数据,通过java代码需要逐层解析比较困难,所以我们又通过第三方框架GSON,使用它可以直接将字符串解析成对象,并且封装成为一个实体类,配合实体类插件GsonFormatPlus,让我们只需通过简单的几行代码就实现数据解析

网络请求-》java-》OKHTTP

数据解析-》java解析-》GSON配合插件解析

网络编程的数据解析部分已经十分的方便了,但网络请求数据部分,通过java代码创建子线程请求到数据,然后又要通过runOnUiThread(new Runnable()方法线程切换到主线程将设数据设置到主线程的控件上,对于开发不便,我们这期学习如何使用OKHTTP框架实现网络请求,解决线程切换的问题

2. 原生HTTP网络访问的缺点

  1. 每次网络访问需要放在子线程里
  2. 每次得到结果需要返回到主线程才能更新控件显示
  3. 需要对各种情况进行处理,没有对状态码判断

3. OKHTTP

概述 - OkHttp (square.github.io)

HTTP是现代应用程序网络的方式。这就是我们交换数据和媒体的方式。有效地执行 HTTP 会使内容加载速度更快并节省带宽。

OkHttp 是一个默认高效的 HTTP 客户端:

  • HTTP/2 支持允许对同一主机的所有请求共享一个套接字。
  • 连接池可减少请求延迟(如果 HTTP/2 不可用)。
  • 透明 GZIP 可缩小下载大小。
  • 响应缓存完全避免了重复请求的网络。

OkHttp 适用于 Android 5.0+(API 级别 21+)和 Java 8+。

3.1 框架引入

框架官网地址

https://github.com/square/okhttp

添加网络请求权限

网络异常,图片无法展示
|

添加依赖

implementation("com.squareup.okhttp3:okhttp:4.9.3")

网络异常,图片无法展示
|

3.2 框架使用

3.2.1 数据请求

 

publicclassMainActivityextendsAppCompatActivity {

 

   @Override

   protectedvoidonCreate(BundlesavedInstanceState) {

       super.onCreate(savedInstanceState);

       setContentView(R.layout.activity_main);

 

       //发起请求

       //无需手动创建子线程,框架默认帮我们创建

 

       //1.创建一个okhttp对象

       OkHttpClientokHttpClient=newOkHttpClient();

       //2.创建一个Request对象,里面存放请求到的数据,调用Request类里的builder()方法,相当于调用了Request的静态方法

       //.url请求的地址

       //.get() 请求的方式 常用的请求方法1.get()   2.post() 这个由后端的接口决定

       //.build()

       Requestrequest=newRequest.Builder()

               .url("http://121.4.44.56/object")

               .get()

               .build();

       //3.将数据放到okHttpClient对象中

       Callcall=okHttpClient.newCall(request);

       //enqueue一个队列,程序可以发起多个请求,将这些请求存在队列中一个一个的处理

       call.enqueue(newCallback() {

           @Override

           publicvoidonFailure(@NonNullCallcall, @NonNullIOExceptione) {

               //请求失败

           }

 

           @Override

           publicvoidonResponse(@NonNullCallcall, @NonNullResponseresponse) throwsIOException {

               //请求成功,通过response对象返回请求到的数据

               Stringresult=response.body().string();

               Log.i("onResponse", "onResponse: "+result);

           }

       });

   }

}

由此我们可以知道okhttp框架相较于传统的网络请求的优势:

优势一:无需自己创建子线程,okhttp自动帮我们创建

优势二:返回的数据不再是数据流,而是转换好的string字符串

优势三:自动处理异常情况,提供onFailure()方法

打印测试结果:

网络异常,图片无法展示
|

3.2.2 数据解析

这是返回的数据还是没有经过解析的,我们可以使用上节课的GSON搭配实体类插件GsonFormatPlus来解析数据

第一步:添加gson依赖

 //添加GSON依赖

   implementation'com.google.code.gson:gson:2.9.0'

网络异常,图片无法展示
|

第二步:创建实体类

我们可以复制json数据,通过实体类插件GsonFormatPlus快速创建

网络异常,图片无法展示
|

第三步:解析数据

//GSON搭配实体类插件`GsonFormatPlus`来解析数据

   Gsongson=newGson();

   Studentstudent=gson.fromJson(result,Student.class);

网络异常,图片无法展示
|

第四步:设置到文本控件上显示

我们先得给文本控件取一个id,为了方便查看,我设置了文本的大小和颜色

网络异常,图片无法展示
|

然后将解析出的数据设置到文本控件上

同样的在okhttp中我们需要切换线程到主线程来设置数据到控件上,说明okhttp框架只帮我们解决了构建子线程的问题,线程切换还是需要自己实现

网络异常,图片无法展示
|

运行可以看到名字已经解析出来并显示在虚拟机上

网络异常,图片无法展示
|

小tips:这里我不知为什么没写线程切换直接跑,也运行出来了,还报了一堆奇怪的错,没搞懂,先记录在这里

网络异常,图片无法展示
|

3.3 MainActivity完整代码

publicclassMainActivityextendsAppCompatActivity {

 

   @Override

   protectedvoidonCreate(BundlesavedInstanceState) {

       super.onCreate(savedInstanceState);

       setContentView(R.layout.activity_main);

 

       TextViewtxtView=findViewById(R.id.txtVId1);

 

       //发起请求

       //无需手动创建子线程,框架默认帮我们创建

 

       //1.创建一个okhttp对象

       OkHttpClientokHttpClient=newOkHttpClient();

       //2.创建一个Request对象,里面存放请求到的数据,调用Request类里的builder()方法,相当于调用了Request的静态方法

       //.url请求的地址

       //.get() 请求的方式 常用的请求方法1.get()   2.post() 这个由后端的接口决定

       //.build()

       Requestrequest=newRequest.Builder()

               .url("http://121.4.44.56/object")

               .get()

               .build();

       //3.将数据放到okHttpClient对象中

       Callcall=okHttpClient.newCall(request);

       call.enqueue(newCallback() {//enqueue一个队列,程序可以发起多个请求,将这些请求存在队列中一个一个的处理

           @Override

           publicvoidonFailure(@NonNullCallcall, @NonNullIOExceptione) {

               //请求失败,打印解析失败原因

               Log.i("onFailure", "onFailure: "+e.getMessage());

           }

 

           @Override

           publicvoidonResponse(@NonNullCallcall, @NonNullResponseresponse) throwsIOException {

               //请求成功,通过response对象返回请求到的数据

               //子线程

               Stringresult=response.body().string();

               Log.i("onResponse", "onResponse: "+result);

 

               //GSON搭配实体类插件`GsonFormatPlus`来解析数据

               Gsongson=newGson();

               Studentstudent=gson.fromJson(result,Student.class);

               //抛出到主线程

               runOnUiThread(newRunnable() {

                     @Override

                     publicvoidrun() {

                         txtView.setText(student.name);

                     }

                 }

               );

 

           }

       });

 

       //优势一:无需自己创建子线程

       //优势二:返回的数据不再是数据流,而是转换好的string字符串

       //优势三:自动处理异常情况,提供`onFailure()`方法

   }

}

4. 在线接口

1.介绍 · fastmock教程 (gitee.io)

fastmock可以让你在没有后端程序的情况下能真实地在线模拟ajax请求,你可以用fatmock实现项目初期纯前端的效果演示,也可以用fastmock实现开发中的数据模拟从而实现前后端分离。

5. Retrofit

网络请求-》java-》OKHTTP-》Retrofit

数据解析-》java解析-》GSON配合插件解析

Retrofit是对http网络请求框架的封装,一般由okhttp来负责网络请求,retrofit对请求接口进行封装。retrofit通过接口和注解来描述我们的网络请求,然后通过client去调用okhttp框架,通过addConverterFactory来实现对返回的json数据进行处理,转换成我们需要的数据类型,可以理解为okhttp的加强版,底层封装了Okhttp

5.1 框架引入

   //添加okhttp依赖/

   implementation("com.squareup.okhttp3:okhttp:4.9.3")

   //添加Retrofit依赖

   implementation'com.squareup.retrofit2:retrofit:2.9.0'

   implementation'com.squareup.retrofit2:converter-gson:2.9.0'

网络异常,图片无法展示
|

5.2 框架使用

5.2.1 创建接口

创建一个接口,返回值是Call类型,使用泛型封装Student类,注意引入包不要用okhttp的

网络异常,图片无法展示
|

importretrofit2.Call;

importretrofit2.http.GET;

 

publicinterfaceApi {

   //http://121.4.44.56/object

   //使用get注解,放入请求的地址的最后一部分,前面的部分会在别处拼接

   @GET("object")

   Call<Student>getStudent();

}

 

5.2.2 数据请求&数据解析

回到MainActivity方法,将之前写的用okhttp框架的所有代码注释,以及删除对于的所有包

使用Retrofit框架来实现同样的功能

值得注意的是Retrofit框架在okhttp的基础上进一步封装,我们无需手动解析数据,也无需抛出线程

//使用Retrofit框架

//1..创建一个Retrofit对象

Retrofitretrofit=newRetrofit.Builder()

   .baseUrl("http://121.4.44.56/")

   .addConverterFactory(GsonConverterFactory.create())//表示以GSON框架解析数据

   .build();

 

//2.获取到Api接口

//返回一个接口实例

Apiapi=retrofit.create(Api.class);

 

//3.通过Api获取到实体类Student

retrofit2.Call<Student>call=api.getStudent();

 

//4.enqueue一个队列,程序可以发起多个请求,将这些请求存在队列中一个一个的处理

call.enqueue(newCallback<Student>() {

   @Override

   publicvoidonResponse(Call<Student>call, Response<Student>response) {

       //请求成功:返回的结果是一个call对象,而不再是response,

       //默认将请求的结果抛回到主线程

       Studentstudent=response.body();

       txtView.setText(student.name);

   }

 

   @Override

   publicvoidonFailure(Call<Student>call, Throwablet) {

       //请求失败

   }

});

5.2.3 日志拦截(Retrofit优化)

Retrofit框架看上去已经很完美了,但是因为它帮我们完成了数据解析,我们无法捕获数据解析是否成功,所以当数据解析失败时通过response.body();是获取不到数据的

面对这个问题同样也有解决办法

我们引入一下依赖

//拦截日志依赖

implementation'com.squareup.okhttp3:logging-interceptor:4.9.3'

网络异常,图片无法展示
|

通过如下工具类进行拦截,使用这个工具类我们通过日志过滤的方法查看请求的状态和数据解析是否成功

 

publicclassRetrofitUtils {

 

   publicstaticRetrofitgetRetrofit(Stringurl) {

       //日志显示级别

       HttpLoggingInterceptor.Levellevel=HttpLoggingInterceptor.Level.BODY;

       //新建log拦截器

       HttpLoggingInterceptorloggingInterceptor=newHttpLoggingInterceptor(newHttpLoggingInterceptor.Logger() {

           @Override

           publicvoidlog(Stringmessage) {

               Log.d("RetrofitMessage","OkHttp====Message:"+message);

           }

       });

       loggingInterceptor.setLevel(level);

       //定制OkHttp

       OkHttpClient.BuilderhttpClientBuilder=newOkHttpClient

               .Builder();

       //OkHttp进行添加拦截器loggingInterceptor

       httpClientBuilder.addInterceptor(loggingInterceptor);

 

       Retrofitretrofit=newRetrofit.Builder()

               .baseUrl(url)

               .addConverterFactory(GsonConverterFactory.create())

               .client( httpClientBuilder.build())

               .build();

 

       returnretrofit;

   }

 

}

使用这个工具类也能简化请求数据的代码,我们只需这么一行代码就能拿到Api接口实例

Apiapi=RetrofitUtils.getRetrofit("http://121.4.44.56/").create(Api.class);

网络异常,图片无法展示
|

通过debug级的日志过滤我们可以查看数据请求的状态信息和数据解析结果,也方便我们排错分析

网络异常,图片无法展示
|

笔记源码

starry陆离/LessonTwo - 码云 - 开源中国 (gitee.com)

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
29天前
|
监控 安全
从 Racket 语言出发,创新员工网络监控软件的框架
在数字化企业环境中,员工网络监控软件对于保障信息安全和提升效率至关重要。Racket 语言凭借其独特特性和强大功能,为开发创新的监控软件提供了新可能。通过捕获和分析网络数据包、记录员工网络活动日志,甚至构建复杂的监控框架,Racket 能够满足企业的定制化需求,为企业信息安全和管理提供强有力支持。未来,基于 Racket 的创新解决方案将不断涌现。
36 6
|
4天前
|
数据采集 存储 JSON
Python网络爬虫:Scrapy框架的实战应用与技巧分享
【10月更文挑战第27天】本文介绍了Python网络爬虫Scrapy框架的实战应用与技巧。首先讲解了如何创建Scrapy项目、定义爬虫、处理JSON响应、设置User-Agent和代理,以及存储爬取的数据。通过具体示例,帮助读者掌握Scrapy的核心功能和使用方法,提升数据采集效率。
28 6
|
12天前
|
机器学习/深度学习 人工智能
类人神经网络再进一步!DeepMind最新50页论文提出AligNet框架:用层次化视觉概念对齐人类
【10月更文挑战第18天】这篇论文提出了一种名为AligNet的框架,旨在通过将人类知识注入神经网络来解决其与人类认知的不匹配问题。AligNet通过训练教师模型模仿人类判断,并将人类化的结构和知识转移至预训练的视觉模型中,从而提高模型在多种任务上的泛化能力和稳健性。实验结果表明,人类对齐的模型在相似性任务和出分布情况下表现更佳。
25 3
|
1月前
|
安全 网络安全 区块链
网络安全与信息安全:构建数字世界的防线在当今数字化时代,网络安全已成为维护个人隐私、企业机密和国家安全的重要屏障。随着网络攻击手段的不断升级,从社交工程到先进的持续性威胁(APT),我们必须采取更加严密的防护措施。本文将深入探讨网络安全漏洞的形成原因、加密技术的应用以及提高公众安全意识的重要性,旨在为读者提供一个全面的网络安全知识框架。
在这个数字信息日益膨胀的时代,网络安全问题成为了每一个网民不可忽视的重大议题。从个人信息泄露到企业数据被盗,再到国家安全受到威胁,网络安全漏洞如同隐藏在暗处的“黑洞”,时刻准备吞噬掉我们的信息安全。而加密技术作为守护网络安全的重要工具之一,其重要性不言而喻。同时,提高公众的安全意识,也是防范网络风险的关键所在。本文将从网络安全漏洞的定义及成因出发,解析当前主流的加密技术,并强调提升安全意识的必要性,为读者提供一份详尽的网络安全指南。
|
2月前
|
存储 SQL 安全
网络安全与信息安全:守护数字世界的坚盾在这个高度数字化的时代,网络安全和信息安全已经成为个人、企业乃至国家安全的重要组成部分。本文将深入探讨网络安全漏洞、加密技术以及安全意识的重要性,旨在为读者提供一个全面的网络安全知识框架。
随着互联网技术的飞速发展,网络安全问题日益凸显。从个人信息泄露到企业数据被盗,再到国家安全受到威胁,网络安全事件层出不穷。本文将从网络安全漏洞的定义与分类入手,探讨常见的网络攻击手段;随后深入解析加密技术的原理及其在保护信息安全中的作用;最后强调提升公众与企业的安全意识的重要性,并提出具体的建议。通过综合运用这些知识点,我们可以更好地构建起一道道坚固的防线,守护我们的数字世界。
|
2月前
|
编解码 分布式计算 网络协议
Netty高性能网络框架(一)
Netty高性能网络框架(一)
|
1天前
|
算法 JavaScript Android开发
|
5天前
|
数据采集 前端开发 中间件
Python网络爬虫:Scrapy框架的实战应用与技巧分享
【10月更文挑战第26天】Python是一种强大的编程语言,在数据抓取和网络爬虫领域应用广泛。Scrapy作为高效灵活的爬虫框架,为开发者提供了强大的工具集。本文通过实战案例,详细解析Scrapy框架的应用与技巧,并附上示例代码。文章介绍了Scrapy的基本概念、创建项目、编写简单爬虫、高级特性和技巧等内容。
21 4
|
5天前
|
网络协议 物联网 API
Python网络编程:Twisted框架的异步IO处理与实战
【10月更文挑战第26天】Python 是一门功能强大且易于学习的编程语言,Twisted 框架以其事件驱动和异步IO处理能力,在网络编程领域独树一帜。本文深入探讨 Twisted 的异步IO机制,并通过实战示例展示其强大功能。示例包括创建简单HTTP服务器,展示如何高效处理大量并发连接。
20 1
|
10天前
|
网络协议 Shell 网络安全
解决两个 Android 模拟器之间无法网络通信的问题
让同一个 PC 上运行的两个 Android 模拟器之间能相互通信,出(qiong)差(ren)的智慧。
17 3