首图

目录

目录

前言

1. 网络优化的三个要点

1. 多维

网络优化应该是多维的,一般情况下,一谈到网络优化,大部分人首先想到的就是流量消耗,但是实际上流量消耗多少只是网络优化的其中一个维度。

只对流量消耗一个维度进行优化是不够的,甚至有的团队即便在流量优化上也没有做好,比如对于网络流量的消耗统计不够全面和精确。

2. 精准

在做网络流量统计时,我们要做精准度量,如果只是获取了具体消耗了多少的值,对于我们定位和解决问题是没有太大的帮助,因为这个值只能表明用户用了多少流量。

如果线上用户反馈 App 消耗流量较多,但是我们不知道这个用户总共使用了 App 多长时间的话,那就不好定位问题所在,如果用户使用 App 的时间比较长,那消耗流量多一些很可能是正常的。

又比如用户反馈 App 在后台消耗流量比较多,但是我们只统计了整体的值,那就无法断定 App 在后台运行时到底消耗了多少流量。

3. 监控

针对网络优化,我们应该建设全面且完善的网络监控体系,不能只监控一个指标,假如只监控网络请求成功率,那我们就只能知道用户大概的网络使用情况,这种粗粒度的监控没办法帮助我们找出并解决问题的根源。

比如线上用户使用了某个功能使用了 1000 次,然后出现了 1 次异常,而且用户点击重试后就恢复正常了。

这样单从数据上来看的话,网络请求的成功率还是比较高的,但是只通过成功率一个值是无法知道这一次异常出现的原因,也就无法避免后续出现这类异常。

2. 网络优化的两个维度

1. 流量维度

流量维度也就是 App 在一段时间内流量消耗的精准度量。

流量消耗大不仅对用户有影响,对公司的运营成本也有影响,比如带宽、服务器数量、CDN 等方面的开支,而且网络请求密集对手机耗电量也有一定的影响。

在流量维度上,我们要做到区分类型、监控异常、上报日志。

  • 区分类型

    我们不仅要知道用户在某个时间段内的具体流量消耗,还要知道用户在不同网络类型(流量、WiFi)下的流量消耗、区分 App 在前台和在后台时的流量消耗。

    只有积累了不同维度的数据,才能快速断定和解决问题。

  • 监控异常

    对于流量统计,我们不仅要知道用户的流量消耗均值,还要知道线上用户消耗流量的异常率。

    这里的异常分为三种:

    1. 流量消耗过多

    2. 请求次数过多

    3. 下载文件过大

    这三个都是我们要注意的异常。

  • 上报日志

    最理想的情况,就是我们对所有的网络请求,在本地都有一个完整的监控,每一个请求的 Request 和 Response 相关的所有信息都全部记录下来。

    服务端可以下发指令控制客户端上传这些数据,客户端也可以在相关数据超过阈值后主动上报。

2. 质量维度

网络请求的质量也非常关键,它直接对应了用户的真实体验,如果网络请求速度慢或请求成功率比较低,都会导致不好的用户体验。

对于网络请求质量的监控,可以从下面几个维度进行区分,以便后续能快速定位和解决问题。

  • 请求时长
  • 请求成功率
  • 失败率
  • Top 失败接口

3. 网络优化的两个误区

  • 只关注流量

    只关注流量消耗,忽视了其他维度。

  • 忽略个体数据

    还有就是做网络监控时只关注均值和整体的数据,忽略了个体的数据。

    比如前面提到的请求成功率的例子,从整体上来看成功率非常高,但是这种数据无法帮助我们改善单次请求。

1. 三个线下测试工具

对于线下测试环境,我们要有一个正确的认识,线下测试是为了把问题尽可能在上线前暴露出来,在线下测试环节,我们要注意下面 4 点。

  • 网络切换

  • 弱网/无网测试

  • 请求是否有误

    接口请求是否有误,比如传了过多的参数或传参不正确;

  • 周期长

    C 端的 App 到了稳定期后,用户可能高达几千万甚至更多,这时 App 功能一般是非常复杂的,而且包含了其他功能,比如性能监控等。

    这些功能的网络请求往往不是实时上报的,所以我们在做流量消耗测试的时候,周期一般会很长,不能只是简单测 10 分钟。

我们要确保我们的 App 在切换网络、弱网或无网时做到下面这两点。

  • 不能中断流程

    有的 App 对安全性要求比较高,如果突然切换网络状态,会导致用户的登录态失效,也就是要用户重新登录。

    这时我们要注意重新登录后 App 会不会重新回到之前的流程中,不能中断用户正在进行的流程。

  • 关闭加载弹窗

    而且在弱网或无网状态下,一定要测试 Loading 弹窗是否会停止,如果不注意的话,在无网的情况下,应用的请求失败了,但是却没有关闭 Loading 弹窗,影响了用户的其他操作。

    如果对无网状态重视不足,就测不出这样的 Bug 。

下面我们来看 3 个常用的线下测试工具:

  • Network Profiler
  • Charles
  • Stetho

1.1 Network Profiler

Network Profiler 是 AS 自带的网络分析工具,它能显示实时网络活动,比如发送网络请求、接受的数据以及连接数等。

1. 点击开始分析。

开始分析

2. 连接视图

然后在 Profiler 下方可以看到连接视图(Connection View),右侧则是某个连接的信息,包括请求时间、响应、请求以及调用栈。

Netwrok Profiler

3. 线程视图
线程视图

4. 请求信息

请求信息

5. 响应信息

响应信息

6. 调用栈

调用栈

1.2 Charles

下面是 4 个比较常用的抓包工具:

  • Charles

    Charles 是使用 Java 开发的,在 Mac 上使用比较多;

  • Fiddler

    在 Windows 上使用得比较多;

  • Wireshark

  • TcpDump

下面我们重点来看下 Charles 的使用, Charles 支持断点功能、模拟数据以及弱网模拟等功能。

1.2.1 基础用法

  1. 在官网上下载 Charles

下载 Charles

  1. 打开 Charles 的代理功能

打开代理功能

  1. 查看电脑 IP 地址

Local Address1

vboxnet2 是虚拟机 Virtual Box 的地址。

Local Address2

  1. 设置 WiFi 代理地址

设置代理主机

  1. 同意连接

    设置代理后,当我们在设备上访问网络时,Charles 会弹出一个是否允许连接的弹窗,我们点击允许(Allow)即可。

允许连接

  1. 安装证书

    如果是抓取 HTTPS ,那就要安装证书,否则请求和响应信息都会是乱码。

安装证书 1

搜索 charles 并选择始终信任。

始终信任

  1. 安装手机证书

安装证书 2

选择安装证书在移动设备后,Charles 会弹出一个代理提示,让我们去 chls.pro/ssl 下载并安装证书。

代理提示

我已经下载过了,所以这里提示的是重新下载,下载后点击安装即可。

下载证书

  1. 添加主机

    然后在 SSL Proxying Settings 中添加我们要抓包的主机地址,这里可以使用通配符 *.* 。

添加主机

  1. 添加网络安全配置

在 res/xml 下添加 network_security_config.xml

NetworkConfig

然后在 Manifest 的 Application 标签中添加该配置。

Applicaiton 网络配置

然后就可以看到抓包结果了。

抓包结果

1.2.2 断点

我们右键点击任意一个请求后,就可以看到断点(Breakpoints)选项。

添加断点

如果想要查看已经添加的断点列表,可以在 Proxy->Breakpoint Settings 中查看。

断点列表1

断点列表 2

如果想只对 Request 或 只对 Response 断点,可以点击断点,然后在编辑断点弹窗中设置。

断点设置

下面看下进入断点后的界面,当我们再次发起打了断点的请求时,可以看到断点界面。

进入断点

当我们点击 Edit Request 标签后,我们可以在这里编辑请求的信息。

编辑请求

当我把 version 改为 3 后,可以看到请求中的参数改成了 3 。

修改 Version

1.2.3 模拟数据

Charles 有一个叫 Map Local 的功能,Map Local 多用于服务端接口未开发完毕,只定义了协议时的情况。

我们可以用 Map Local 模拟自己想要的假数据,可以自由模拟各种脏数据,这样就算服务端开发进度比较慢,不会影响客户端的开发进度,除了 Map Local,也可以使用 MockK 等用于测试的模拟框架来实现功能。

下面我们来看下怎么使用 Map Local。

然后右键点击请求,弹出菜单的最下方就是 Map Local。

打开 Map Local

点击 Map Local 后,可以看到 Edit Mapping 弹窗。

Edit Mapping

原始的响应是下面这样的。

原始 JSON

然后建立一个 maplocal 文件,把 group 里的 count 改成 20 。

maplocal

当客户端再次发起相同的请求时,就可以看到 group 的 count 的值变成了 20 。

修改后的返回结果

如果想关闭 Map Local,可以点击 Tools -> Map Local,然后把 Enable Map Local 的勾选取消掉。

关闭 MapLocal1

关闭 MapLocal2

1.2.4 弱网模拟

Charles 支持弱网模拟功能,点击 Proxy -> Start throtting。

打开限流

勾选 Enable Throttling 后,就开启了限流功能,限流功能支持下面几个选项。

  • 预设值(Throttle preset)

  • 带宽(Bandwidth)

  • 利用率(Utilisation)

  • 往返延迟(Round-trip-latency)

  • MTU(传输 TCP 包的最大尺寸)

  • 可靠性(Reliability,丢包)

  • 稳定性(Stability,抖动)

  • 不稳定质量范围(Unstable quality range)

    主要针对 Statbility 中设置的范围;

编辑限流

下面是一些常用的预设值。

预设值

下面这个请求,在限流前的总处理时间是 177 毫秒。

限流前

当开启了弱网模拟后,变成了 9.3 秒。

限流后

1.3 Stetho

看完了 Charles,下面我们来学习下 Stetho,Stetho 是一个强大的应用连接桥,可以连接 Android 和 Chrome,有网络监控、视图查看、数据库查看、命令行扩展等功能。

1.3.1 Stetho 用法

  1. 添加依赖。
 // Android 应用调试工具
implementation 'com.facebook.stetho:stetho-okhttp3:1.5.1'

这个库是 Stetho 针对 OkHttp 的实现。

  1. 初始化

初始化 Stetho

  1. 添加拦截器

添加 Stetho 拦截器

  1. 打开 Chrome inspect

在 Chrome 中输入 Chrome://inspect ,然后就可以看到设备上的 Chrome 已经打开的标签,下方就是打开了 Stetho 调试的 App。

inspect

  1. 打开 DevTools

点击豆芽下面的 inspect 后,就可以看到 DevTools,点击 DevTools 中的 Network 标签,就可以看到 App 发出的请求和接收到的响应等数据。

Stetho DevTools

由于 Stetho 的抓包功能没那么强大,所以一般情况下不会用 Stetho 作为抓包工具。

2. 线上监控的三个要点

在看获取网络流量前,我们先来看下线上监控的三个要点:服务端监控、客户端监控以及异常监控。

2.1 服务端监控

1. 耗时统计维度

对于服务端的监控,我们要注意请求的耗时,而且耗时要分多个维度区分。

  • 地域

    具体是哪个省、哪个城市的请求速度比较慢;

  • 时间段

  • 版本

  • 机型

2. 失败率

服务端要统计失败率:

  • 请求失败

  • 业务失败

    业务相关的失败也是失败,比如网络请求确实成功了,但是用户没有拿到自己需要的数据,对于失败率的统计要全面,这样衡量的指标才能更敏锐地感知线上的异常波动;

3. Top 失败接口

同时在 APM 后台,我们最好统计一下一段时间内,比如 1 天或 1 周内,排行 Top 的失败接口或异常接口,每隔一段时间就进行一次统计,这样就能知道哪些接口不稳定,以便进行针对性的优化。

2.2 客户端监控

客户端监控比服务端监控更关键,在客户端的监控则更全面,能拿到更多的数据。

我们要在线上监控的数据包括请求具体耗时、成功率、错误码以及图片加载每一步的耗时。

虽然图片加载耗时和成功率在服务端也是可以统计的,但是服务端拿到的数据不完整等,因为很多请求压根没有到服务端就失败了。

而且服务端传过来的数据加上网络通道的延迟时间,肯定比服务端统计到的时间要长,所以我们要在客户端也加上统计。

1. API 监控

客户端能拿到请求的每一个步骤的信息,包括 DNS 解析时间、建立连接的时间、请求时间以及网络包大小等信息。

同时我们可以记录用户每一次网络请求的操作,比如具体请求了哪些接口,请求是否成功以及失败的原因,这些信息我们都能作为监控的基础信息传给 APM 服务端,在后面会介绍如何监控网络请求的每一步。

2. 图片监控

同时还要注意做图片监控,一张图片消耗的流量可能比 5 个甚至更多接口的数据还要多。

3. 网络容灾机制

假如某一天我们的用户量突然暴涨,按服务器可能是扛不住这个压力的,对于服务端来说,可以用备用服务器分流,避免把主服务器搞垮。

而我们客户端也可以做一个策略,就是在一定时间内,网络请求失败了多次时,就不再进行网络请求。

3.2 异常监控

异常监控的目的,是提升我们对异常的感知灵敏度,而不是被动等待用户反馈。

1. 服务器防刷

在服务端,我们要判断是不是有人在刷我们的服务器,也就是恶意攻击,如果检测到有人在刷服务器,我们可以锁定 IP 拒绝这些 IP 访问。

2. 异常兜底

在客户端,我们可以加上主动预警能力,比如我们下载了一个超过设定值的文件,客户端在下载后就可以把这个结果上报给服务器,表明现在遇到了异常,需要研发同学进一步确认。

在一些场景下,服务端可能出现流量过多扛不住的情况,这时客户端可以做一个兜底策略,如果在一定时间内,比如 30 秒内,接口请求连续失败 5 次,那就不允许持续访问,同时把重试时间设长一些。

3. 单点问题追查

假如线上用户反馈 App 消耗流量过多,或者是在后台时消耗流量较多,我们都可以具体分析用户下的网络请求日志,以及下发命令查看具体时间段的流量消耗。

3. 三个线上监控方案

有的问题只在线上出现,在线下发现不了,比如在线下测试某个版本的时候,H5 包不一定是新版本,但是到了线上后,部分用户可能会被命中,然后下发了新版本的包。

而这些包如果没有经过压缩,这样的异常就无法在线下的测试环境中全部发现,只能通过线上监控发现。

下面我们来看下三个线上监控方案:

  • OkHttp 事件监听器
  • NetworkStatsManager
  • TrafficStats

这三个方案中 OkHttp 事件监听器能获取到的数据最细致,也最实用,而 NetworkStatsManager 和 TrafficStats 主要是用于获取流量消耗。

3.1 OkHttp 事件监听器

3.1.1 自定义事件监听器

下面我们来看下如何结合 OkHttp 获取网络请求质量数据,OkHttp 给我们留了一个事件监听器 EventListener 回调,我们可以自己实现这个监听器,监听每一次的请求。

首先定义一个 Model,用于存储请求和响应相关数据,这里为了演示只加上了部分数据,大家可以根据自己的需要制定自己的 Model。

OkHttpEvent

创建 OkHttpEventListener,并重写我们想要的方法,这里为了演示只重写了部分方法,OkHttpEventListener 提供了非常多的方法,大家可以根据自己的需要重写。

OkHttpEventListener

然后设置 OkHttpClient 的事件监听器工厂 。

设置 EventListener

设置了工厂后,我们就能拿到每个网络请求的每一步的耗时和相关数据,包括 DNS 解析事件、请求事件、响应时间、响应字节数等数据,这些都是我们做线上监控必不可少的数据支撑。

3.1.2 自定义 GlideModule

自定义 GlideModue 是为了监控图片加载的过程,下面我们来看下怎么监控 Glide 加载图片过程的耗时和相关数据。

首先添加插件和依赖。

// Kotlin 插件
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'android {// ...
}dependencies {// ...// 图片加载kapt 'com.github.bumptech.glide:compiler:4.11.0'implementation 'com.github.bumptech.glide:glide:4.11.0'implementation "com.github.bumptech.glide:okhttp3-integration:4.11.0"
}

然后定义一个 GlideModue,替换 ModelLoader 工厂。

自定义 GlideModule

点击 Build -> Clean Project,再点击 Build -> Make Project。

Clean Project

然后把 Glide 替换为 GlideApp。

GlideApp

然后我们就可以在自定义的事件监听器里监听到图片加载过程的耗时和大小了。

3.1.3 OkHttp 最大并发请求数

关于请求的频率,我们可以看下 OkHttp 默认的请求池,在 OkHttp 的 Dispatcher 分发器中,有一个 executeService 线程池,它的核心池大小为 0 ,最大值是整型的最大值。

但这并不是意味着通过 OkHttp 发送的网络请求可以并发无数个,对于 IO 密集型任务我们可以多发送一些,因为这类任务对 CPU 消耗不大,但是我们还是要注意,单个 App 能创建的线程数也是有上限的。

虽然线程池大小没有限制,但是在请求执行前会在 promoteAndExecute() 方法中判断是否已超出最大请求数量,而判断的依据就是 maxRequests(最大并发请求数) 和 maxRequestsPerHost(单个主机最大并发请求数)。

之所以要设置单个主机最多能并发执行的请求数量,防止某个域名的请求过多,导致其他域名没有机会执行。

假如我们的项目中已经做了域名收敛,只有一个域名,就可以增加单个域名下的数量限制,这样同时执行的网络请求的数量就能多一些。

OkHttp Dispatcher

3.1.4 区分前后台流量

之所以要在日志中区分前后台流量,是因为很多用户会担心 App 一直在后台消耗流量,如果粗粒度地只获取流量数据,是不知道这些流量有多少是 App 在后台运行时消耗的,这样的话不要说解决用户反馈的问题,就连定位问题都定位不了。

通过 ProcessLifecycleOwner 给请求数据打上标志,这样我们就可以分别知道用户在前台和后台的流量消耗,而且用户反馈时,我们就可以自己查看该用户的流量消耗统计,判断是否存在异常。

这个方案存在的不足,就是当用户在 30 秒内切换 App 的前后台状态时,会有一定的误差,但是这个误差是在可接受范围内的。

使用这种方式,再结合 APM 后台设置的阈值,让客户端在流量消耗达到阈值后自动上报,从而实现更精准的流量消耗监控。

下面我们来看下怎么使用 ProcessLifecycleOwner 。

1. 添加依赖

有很多 AndroidX 的库自带了 process 库,大家可以在 External Libraries 中看下有没有,有就不用添加下面这个 库了。

dependencies {// AndroidX Lifecycle 进程implementation 'androidx.lifecycle:lifecycle-process:2.2.0'}
2. 定义应用生命周期观察器

AppLifecycleOwner

3. 开始监听

添加观察者

4. ProcessLifecycleOwner 原理

在 ProcessLifecycleOwner 出来之前,我们自己也可以通过计数的方式来判断是不是所有 Activity 都隐藏了,是的话则断定为应用隐藏了。

而 ProcessLifecycleOwner 只是帮我们把这件事情做了,在 ProcessLifecycleOwner 的初始化方法 ini 中调用了 attach 方法,而 attach 方法中实现了 Activity 生命周期回调接口。

以 onStart 为例,ProcessLifecycleOwner 中有一个 mStartdCounter,每次有一个 Activity 的 onStart 方法被调用了,mStartdCounter 就会加 1,如果 mStartCounter 等于 1 ,则表明应用启动了,然后 ProcessLifecycleOnwer 就会通过 mRegistry 调用我们自定义的 onAppForeground 方法。

ProcessLifecycleOwner

3.1.5 四步上传数据

下面是上报性能日志的大概的四个步骤。

  1. 后台任务

    在 App 启动时,执行一个后台任务;

  2. 间隔统计

    这个任务每隔一段时间(如 30 秒内)就获取网络数据;

  3. 自定数据

    自己维护一份数据统计,给数据加上标志,记住用户在前后台的流量消耗总量;

  4. 上报数据

    在合适的时机(如用户反馈、达到阈值、处于 WiFi 网络下)把数据上报到 APM 后台,这样对用户的流量就不会造成影响,而且数据也能作为流量治理依据;

3.2 NetworkStatsManager

NetworkStatsManager 是 API 23 后的流量统计管理器,它可以获取某个时段的流量信息,也可以获取不同网络类型下的流量消耗,它最大的不足就是用户体验比较差,需要用户开启“查看使用情况”权限。

下面是一些使用网络或对流量的消耗比较多的场景。

  • API 请求

  • 升级包

    各种升级的资源包,比如 App 升级包、WebView 使用的 H5 Zip 包、RN 使用到的 bundle 包等;

  • 配置

    在 App 做大后,还要用到各种配置信息,比如做 A/B 测试时使用的配置信息、运营活动下发的配置信息;

  • 图片

    图片是流量消耗的大户,图片的下载和上传都非常消耗流量;

  • 监控

    在 App 做大后,还会做各种监控功能,比如 APM 监控的各种数据都需要网络才能上传到服务端;

3.2.1 流量优化的三个要点

在讲怎么用 NetworkStatsManager 获取流量消耗前,我们要先了解下流量优化的三个要点。

1. 不能只看绝对值

绝对值不能作为流量消耗偏高的唯一统计标准,不能说 App 消耗了 10M 的流量,那就要马上去优化。

绝对值的对比是没有意义的,比如用了 App 30 分钟,浏览了很多的商品或视频,那用了 10M 可能已经算少了。

2. 对比竞品

那要以什么为标准呢?我们最好是对比竞品,对比两个 App 在相同的场景下的流量消耗。

比如和竞品一起跑一个发布评论的主流程,这里要注意,要保证两个 App 发布的评论是相同的,而且图片也是相同的,以保证变量是唯一的。

这样对比一下,如果我们和竞品的流量消耗差距比较大,那我们对流量优化的步伐,就应该加快一些,这个绝对值跟竞品的对比,应该结合使用。

3. 设定预期

我们要判断一下新上功能的流量消耗,比如我们要预期是用户使用新功能后,单次消耗流量应该为 300K 左右,但是上线后超过了 300K 时,我们就要确认下流量消耗是否偏高。

3.2.2 NetworkStatsManager 基本用法

如果我们不使用 OkHttp 的 EventListener ,而是用了 NetworkStatsManager,那么当用户反馈说某个时间段内的流量消耗较多时,我们就也可以在后台给客户端下发一个指令,让客户端上传特定时间段内的流量统计数据,然后结合用户使用时长判断 App 的流量消耗是否真的存在异常。

1. readNetworkStats

readNetwrokStats

2. querySummary

下面是常用的 querySummary 方法各个参数的介绍。

querySummary

querySummary 的内部处理流程如下。

querySummary 处理流程

在这个流程中,最重要的就是在 NetworkStatsCollection 的 mStats 中读取系统已经保存好的网络统计数据。

NetworkStatsCollection

3. 申请授权

使用 NetworkStatsManager 需要额外的权限 PACKAGE_USAGE_STATS , 这个权限是系统权限,需要主动引导用户开启应用的“有权查看使用情况的应用”权限。

首先在清单文件中权限声明。

添加权限

然后在代码中主动引导用户开启权限。

引导授权

3.3 TrafficStats

TrafficStats 是 API 8 后提供的一种流量数据统计方案,它统计到的数据其实是我们手机上次重启后的流量消耗,也就是重启前的流量是统计不到的。

TrafficStats 常用方法:

  • getUidRxBytes(int uid)

    获取指定 Uid 的接收流量;

  • getTotalTxBytes()

    获取 App 总发送流量;

下面我们是 TrafficStats 的使用方式。

getMobileRx

一般情况下不使用 TrafficStats,因为它存在下面两个问题:

  • 无法获取特定应用的流量消耗

    无法获取特定应用的流量消耗,只能给我们一个总的流量消耗值,这个值对于我们解决问题来说帮助不大。

  • 无法获取特定时间段的流量消耗

    比如线上某个用户反馈发现昨天 App 的流量消耗过多,这时我们是无法知道用户具体消耗了多少流量的。

4. 三个流量优化方案

4.1 数据缓存

4.1.1 OkHttp 缓存

如果我们仔细跟一下自己项目中的接口,就会发现很多对实时性没有那么高要求的接口,使用缓存不仅可以节约流量,而且能大幅提升数据访问速度。

我们常用的网络库,比如 OkHttp 和 Volley,都有比较好的缓存实践。

而且没做缓存对用户体验也不好,一般的 App 会在打开后显示一个无数据的界面,和展示上一次的数据相比,这个用户体验其实是比较差的。

1. 无网拦截器

下面我们重点看下 OkHttp 的缓存实践,首先定义一个无网拦截器。

NoNetworkInterceptor

然后是给 OkHttpClient 添加拦截器。

添加无网拦截器

添加了无网络拦截器后,当无网络的情况下打开我们的 App 时,也能获取到上一次的数据,也能使用 App,这样就能提升用户体验。

2. OkHttp 缓存处理流程

OkHttp 的缓存拦截器对于请求的处理流程如下。

OkHttp 缓存处理流程

4.1.2 过期时间与增量更新

1. 过期时间

在服务端返回的数据中加上一个过期时间,这样我们每次请求的时候判断一下有没有过期,如果没有过期就不需要去重新请求。

2. 增量更新

数据增量更新的具体思路,就是在数据中加上一个版本的概念,每次接收数据都进行版本对比,只接收有变化的数据。

这样传输的数据量就会减少很多,比如省市区和配置等数据比较少更新,如果每次都要请求省市区的数据,这就是在浪费流量。

我们只需要更新发生变化的数据,因为和服务器相关比较密切,在这里就不给大家举例了。

4.2 数据压缩

1. Gzip

对于 Post 请求,Body 是用 Gzip 压缩的,也就是请求的时候带上 Gzip 请求头,服务端返回的时候也加上 Gzip 压缩,这样数据流就是被压缩过的。

2. 压缩请求头

请求头也占用一定的体积,在请求头不变的情况下,我们可以只传递一次,以后都只需要传递上一次请求头的 MD5 值,服务端做一个缓存,在需要请求头中的某些信息时,就可以直接从之前的缓存中取。

3. 合并网络请求

每一个网络请求都会有冗余信息,比如请求头,而合并网络请求就可以减少冗余信息的传递;

4.3 图片压缩

1. 缩略图

图片压缩的第一个手段,就是在列表中优先使用缩略图,因为展示原图会加大内存消耗和流量消耗,而且在列表中直接展示原图没有意义。

下面是原图和缩略图的对比大小,缩略图尺寸为原图的 50%,大小为原图的 10%。

缩略图对比

2. WebP

图片压缩的第二个手段,就是使用 Webp 格式,下面是同一张图片在 PNG 格式和 WebP 格式下的对比,WebP 格式的大小为 PNG 格式的 51%。

WebP 对比

3. Luban

比如我们在上传图片的时候,做一个压缩比如在本地是一个 2M 的图片,完整地上传上去意义不大,只会增加我们的流量消耗,最好是压缩后再上传。

而在图片压缩上做得比较好的就是鲁班,下面我们来看下鲁班的使用方法。

首先添加依赖。

dependencies {// 图片压缩implementation 'top.zibin:Luban:1.1.8'
}

然后添加对图片进行压缩。

鲁班压缩

下面这张图片的原始大小为 1.6M,压缩后变成了 213KB,体积为原始大小的 13%。

图片压缩前后

5. 网络请求质量优化

在前面我们学习了网络请求流量优化,但是实际上,对用户体验破坏最大的是网络请求质量差,很多同学忽略了这点。

因为我们一般在开发或测试阶段,都是在公司用 WiFi 测试,网络质量比较好,假设我们的 App 在流量消耗上问题不大,但是用户经常反馈界面打不开、打开慢、图片加载不出来等问题。

这时用户很有可能会卸载我们的 App ,转向竞品,只有在网络请求质量高,用户体验好,继续使用我们的 App 时,用户才有可能遇到流量消耗的问题,所以网络质量优化比流量优化更关键。

网络质量优化的两个指标:

  1. 网络请求成功率
  2. 网络请求速度

这两个指标都会影响用户体验,在介绍网络请求质量优化前,我们先来看下一个 Http 请求的过程。

  1. 发出请求

    客户端发出一个请求,这个请求到达运营商的 DNS 服务器,然后被解析成对应的 IP 地址;

  2. 创建连接

    第二步就是创建连接,会走 TCP 三次握手,然后根据 IP 地址找对对应的服务器,发送一个请求;

  3. 返回资源

    服务器找到对应的资源,然后原路返回给客户端;

5.1 HttpDNS

首先来看怎么在发出请求这一步上优化,网络请求成功率与速度一上来就受 DNS 服务器的影响,如果我们的 DNS 解析到 IP 地址的过程被劫持或 DNS 解析慢,都会严重影响用户体验。

DNS 被劫持的结果就是用户得到的数据并不是我们真实想要提供给用户的数据,如果 DNS 解析慢,那用户等待的请求时间就会变长。

所以 DNS 优化是网络质量优化的第一步,我们使用 HttpDNS,绕过运营商域名解析过程,HttpDNS 不是使用传统的 DNS 协议,向 DNS 服务器的 53 端口发送请求,而是使用 Http 协议,向服务器的 80 端口发送请求。

这样做的好处有两个:

  1. 防劫持

    降低 Local DNS 劫持,绕过运营商域名解析过程;

  2. 提升速度

    降低平均访问时长,因为节省了一次解析过程;

腾讯云和阿里云都提供了 HttpDNS 服务,具体的实现可能看他们的官方文档。

5.2 Http 协议版本优化

刚刚说到了网络请求的第二步是创建连接,当中涉及 TCP 三次握手,这个过程是比较长的,如果每次请求都要走三次握手,那这个效率是比较低的。

所以 Http 的不同版本对这点的优化也非常多,下面是 Http 协议不同版本之间的主要区别。

  • Http 1.0

    较老的版本,现在已经很少见到用这个版本的服务了,它最大的缺点就是 TCP 连接不复用,每个 TCP 连接只能发送 1 个请求,如果要请求别的资源,就必须重新建立一个连接。

    TCP 创建连接的成本非常高,需要三次握手,并且在开始阶段发送速度比较慢,也就是 Http 1.0 的性能非常差。

  • Http 1.1

    Http 1.1 的出现只比 1.0 晚了半年,它最大的变化就是引入了持久连接,从这个版本开始,是默认不关闭的,可以被多个网络请求复用,这样效率就有了很大的提升。

    它还是有些缺陷,就是它虽然允许 TCP 复用,但是同一个 TCP 连接里面的所有数据通讯必须按顺序来,也就是处理完一个请求后,再响应下一个请求。

    如果前面的网络请求比较慢,那后面的请求也只能等着。

  • Http 2.0

    Http 2.0 是一个二进制协议,它最大的改进就是客户端和服务端可以同时发送多个请求和响应,不需要像 Http 1.1 一样按顺序请求,是一个双向的实时通信。

    这点是 Http 2.0 相对于 Http 1.1 的最大的改进,大家以后要跟服务端配合时,有得选的前提下,尽可能选择高版本的 Http 协议。

5.3 资本优化

最后一个优化方案就是砸钱,常见的手段有 CDN 加速、提高带宽、动静资源分离。

大家需要注意,使用 CDN 后,如果某个资源需要更新,更新完成后是需要清理缓存的,这些优化不涉及客户端,同时也不要忘了减少传输量,注意请求的时机和频率,这一条和我们前面讲到的流量优化相关。

参考资料

  • Top团队大牛带你玩转Android性能分析与优化
  • macOS Charles 4.x版本的安装及使用
  • Setting up Charles to Proxy your Android Device
  • 网络安全配置
  • Charles网络设置
  • Stetho
  • Android应用流量统计——NetworkStatsManager使用
  • AppOpsManager权限检测适配
  • Android中的uid
  • Glide 4.X 使用自定义okhttp 加载图片(忽略https验证)
  • ProcessLifecycleOwner判断Android应用程序前后台切换
  • NetworkStatsCollection
查看全文
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

相关文章

  1. Flutter引用外部包

    Flutter外部包网站:https://pub.dev/ Flutter使用pubspec文件管理应用程序的assets(资源,如图片、package等)。1.引用外部包的方法 在pubspec.yaml,添加依赖项,如添加english_words包:dependencies:flutter:sdk: flutterenglish_words: ^3.1.02.安装依赖 在Android Studio…...

    2024/5/7 19:43:45
  2. Intellij IDEA中使用Protobuf的正确姿势

    Intellij IDEA中使用Protobuf的正确姿势一、.proto文件语法高亮显示需要安装Protobuf Support插件依次点击Intellij中的“File”-->"Settings"-->"Plugins"-->"Browse repositories",如下所示:输入Protobuf,如下所示安装完后,重启I…...

    2024/5/6 23:14:30
  3. 触发器

    触发器: 概念: 触发器是一种特殊类型的存储过程,在满足定义条件操作时触发,并自动执行触发器中预先设定好的定义的语句集合。 1、触发器是特殊的存储过程 2、触发器是在对表操作时,满足条件就科一自动调用预先编译的sql语句触发器是个被动技能:被动技能就是提前编译好触发…...

    2024/5/7 18:53:31
  4. Solr自动更新索引

    前言 几年前在集成solr版本4.x和6.x 时,曾搞过定时自动更新索引的功能;时过境迁,这次基于solr8.5.1版,来搞 定时自动更新索引的功能,顺便做个笔记,省得下次又需要采坑本文solr版本基于8.5.1solr定时更新索引的思路 具体思路:通过定时器定时调用 resultful接口,从而让solr…...

    2024/5/7 23:54:14
  5. python---生成器函数 “for i in generator()”,执行步骤分析

    我想说现在在网上查找一个问题,全是copy的一堆定义和概念,读了一圈还是蒙。至少也得有个演示代码吧(吐槽)。。。。 直接来看代码 def foo(num):print("starting")while num<10:num=num+1yield num #yeild关键之->生成器函数print("end") for …...

    2024/5/6 15:07:23
  6. Qt 大于等于0的正整数 正则表达式

    Qt 大于等于的正整数 正则表达式 QRegExp regExp1(“0|[1-9]\d+$”);...

    2024/5/5 15:30:58
  7. 手撸一个SpringBoot缓存系统

    缓存是最直接有效提升系统性能的手段之一。个人认为用好用对缓存是优秀程序员的必备基本素质。 本文结合实际开发经验,从简单概念原理和代码入手,一步一步搭建一个简单的二级缓存系统。一、通用缓存接口1、缓存基础算法 FIFO(First In First Out),先进先出,和OS里的FIFO思…...

    2024/5/5 15:10:11
  8. 安装Java开发环境 IntelliJ IDEA(以Java1.8为例)

    文章目录准备环境安装Java编译器添加Java环境变量安装ideaHello World! 准备环境 Windows10主机 java软件包,IntelliJ IDEA安装包安装Java编译器添加Java环境变量安装idea此时idea安装完成,进行激活即可(可以支持正版,或者…)Hello World!...

    2024/4/30 2:02:30
  9. Java基础 throw与throws以及异常处理

    Java基础 throw与throws以及异常处理 throw throw通常用与在java程序中抛出异常,非捕获。 public static void main(String[] args) {String s = "abc";if(s.equals("abc")) {throw new NumberFormatException();} else {System.out.println(s);}//functi…...

    2024/4/30 2:02:26
  10. 在Windows实现类似MacOS的时间壁纸,编写脚本自定义自己喜欢的壁纸

    在目前的Windows 10系统版本上,系统原生还没有支持时间壁纸,但是我们只要下载安装一个WinDynamicDesktop软件就可以在自己的Windows 10系统上,体验到MacOS一样的时间壁纸功能。 通过该软件,可以实现日出、白天、日落、夜晚显示不一样的壁纸。 1.准备工作 GitHub下载WinDyna…...

    2024/5/6 3:25:13
  11. 2020-08-17

    实现绘制圆点逐渐放大,代码 代码如下:package com.chy.animateview;import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.os.Bundle; import android.view.View;import android…...

    2024/4/30 2:02:21
  12. 看小说你还在翻阅书本或者滑滑手机吗?小编已经只需一个MP3就可以达到阅读的境界

    原标题:运用Python爬虫下载有声小说 前言:小编开头这样写除了是为了吸引读者的眼球之外,事实上也是如此,我们只需把我们自己想听的小说mp3下载到内存卡中,然后准备一个耳机和MP3就行了。为什么是MP3呢?小编觉得MP3虽然没有手机功能多,但是它的质量比较轻,便于携带。文章…...

    2024/5/8 4:43:47
  13. 蛙泳

    Day-1 熟悉水性 盆子盛水埋头连续呼吸 10次 * 8组Day-2 蛙泳腿 蛙泳腿4步动作 20次 * 6组 蛙泳腿2步动作 20次 * 8组Day-3 蛙泳腿2步动作 20次 * 6组 蛙泳腿2步动作+仰脖子抬头 20次 * 6组Day-4 蛙泳腿和呼吸的配合 蛙泳腿2步动作 20次…...

    2024/5/6 15:07:45
  14. docker容器运行python指令

    //创建镜像 py1 是镜像名称 最后的"."不可缺少 它指定了镜像构建过程中的上下文环境的目录 docker build -t py1 . //13008:5000 映射端口 5000映射到13008端口上 -v /dockerFile:/codeData复制文件夹 //--name 别名 --restart 重启状态always是一直开启 最…...

    2024/5/6 17:46:58
  15. CSS盒子阴影

    <!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>CSS盒子阴影</title><style> div…...

    2024/4/30 2:02:08
  16. python之列表删除del

    ...

    2024/5/7 21:28:23
  17. 加载静态链接库lib

    需要引入两个文件,如下所示#include "FRI_Reader.h" #pragma comment(lib,"FRI_Reader.lib")...

    2024/5/5 22:59:07
  18. ABP启动模板

    首先ABP CLI的安装以及基本指令这些就不说了,官网上写的很清楚。目前ABP的前端部分只支持ASP.NET Core MVC / Razor Pages和Angular,移动端支持React Native。 初学者建议跟着官网https://docs.abp.io/zh-Hans/abp/latest/Tutorials/Part-1?UI=MVC这个指引做一遍,体验一下A…...

    2024/4/30 2:01:54
  19. zbursh2021尝新,安装包

    链接:https://pan.baidu.com/s/1EQ_klB-WXZ1HXLe0Yn_tdw 提取码:gajh...

    2024/4/30 2:02:04
  20. 深入理解JavaScript作用域和作用域链

    前言 JavaScript中有一个被称为作用域(Scope)的特性。虽然对于许多新手开发者来说,作用域的概念并不是很容易理解,本文我会尽我所能用最简单的方式来解释作用域和作用域链,希望大家有所收获! 想阅读更多优质文章请猛戳GitHub博客 作用域(Scope) 1.什么是作用域 作用域是在运…...

    2024/4/30 2:01:46

最新文章

  1. Java面试题:解释Phaser类的作用以及它如何帮助多线程同步

    Phaser 是 Java 并发包 java.util.concurrent 中的一个同步辅助类&#xff0c;它用于多线程之间的同步。Phaser 的设计灵感来自于“相位”的概念&#xff0c;它允许多个线程在多个不同的阶段&#xff08;phase&#xff09;中相互协调&#xff0c;从而实现复杂的线程协作。 以下…...

    2024/5/8 5:51:41
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言&#xff0c;在此感激不尽。 权重和梯度的更新公式如下&#xff1a; w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/5/7 10:36:02
  3. 腾讯云云原生数据库TDSQL-C mysql 以及项目怎么接入

    要接入腾讯云的云原生数据库TDSQL-C的MySQL版本&#xff0c;并将它用于你的项目中&#xff0c;你需要按照以下步骤进行&#xff1a; 创建TDSQL-C的MySQL数据库实例&#xff1a; 登录腾讯云控制台。在产品搜索框中搜索TDSQL-C&#xff0c;然后选择它。在TDSQL-C的产品页面上&…...

    2024/5/4 6:23:44
  4. WPS二次开发专题:WPS SDK实现文档打印功能

    作者持续关注WPS二次开发专题系列&#xff0c;持续为大家带来更多有价值的WPS开发技术细节&#xff0c;如果能够帮助到您&#xff0c;请帮忙来个一键三连&#xff0c;更多问题请联系我&#xff08;QQ:250325397&#xff09; 在办公场景或者家教场景中经常碰到需要对文档进行打印…...

    2024/5/6 20:11:22
  5. 动态规划刷题(算法竞赛、蓝桥杯)--饥饿的奶牛(线性DP)

    1、题目链接&#xff1a;饥饿的奶牛 - 洛谷 #include <bits/stdc.h> using namespace std; const int N3000010; vector<int> a[N];//可变数组vector存区间 int n,mx,f[N]; int main(){scanf("%d",&n);for(int i1;i<n;i){int x,y;scanf("%…...

    2024/5/7 17:16:20
  6. 416. 分割等和子集问题(动态规划)

    题目 题解 class Solution:def canPartition(self, nums: List[int]) -> bool:# badcaseif not nums:return True# 不能被2整除if sum(nums) % 2 ! 0:return False# 状态定义&#xff1a;dp[i][j]表示当背包容量为j&#xff0c;用前i个物品是否正好可以将背包填满&#xff…...

    2024/5/7 19:05:20
  7. 【Java】ExcelWriter自适应宽度工具类(支持中文)

    工具类 import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellType; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet;/*** Excel工具类** author xiaoming* date 2023/11/17 10:40*/ public class ExcelUti…...

    2024/5/7 22:31:36
  8. Spring cloud负载均衡@LoadBalanced LoadBalancerClient

    LoadBalance vs Ribbon 由于Spring cloud2020之后移除了Ribbon&#xff0c;直接使用Spring Cloud LoadBalancer作为客户端负载均衡组件&#xff0c;我们讨论Spring负载均衡以Spring Cloud2020之后版本为主&#xff0c;学习Spring Cloud LoadBalance&#xff0c;暂不讨论Ribbon…...

    2024/5/8 1:37:40
  9. TSINGSEE青犀AI智能分析+视频监控工业园区周界安全防范方案

    一、背景需求分析 在工业产业园、化工园或生产制造园区中&#xff0c;周界防范意义重大&#xff0c;对园区的安全起到重要的作用。常规的安防方式是采用人员巡查&#xff0c;人力投入成本大而且效率低。周界一旦被破坏或入侵&#xff0c;会影响园区人员和资产安全&#xff0c;…...

    2024/5/7 14:19:30
  10. VB.net WebBrowser网页元素抓取分析方法

    在用WebBrowser编程实现网页操作自动化时&#xff0c;常要分析网页Html&#xff0c;例如网页在加载数据时&#xff0c;常会显示“系统处理中&#xff0c;请稍候..”&#xff0c;我们需要在数据加载完成后才能继续下一步操作&#xff0c;如何抓取这个信息的网页html元素变化&…...

    2024/5/8 1:37:39
  11. 【Objective-C】Objective-C汇总

    方法定义 参考&#xff1a;https://www.yiibai.com/objective_c/objective_c_functions.html Objective-C编程语言中方法定义的一般形式如下 - (return_type) method_name:( argumentType1 )argumentName1 joiningArgument2:( argumentType2 )argumentName2 ... joiningArgu…...

    2024/5/7 16:57:02
  12. 【洛谷算法题】P5713-洛谷团队系统【入门2分支结构】

    &#x1f468;‍&#x1f4bb;博客主页&#xff1a;花无缺 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 花无缺 原创 收录于专栏 【洛谷算法题】 文章目录 【洛谷算法题】P5713-洛谷团队系统【入门2分支结构】&#x1f30f;题目描述&#x1f30f;输入格…...

    2024/5/7 14:58:59
  13. 【ES6.0】- 扩展运算符(...)

    【ES6.0】- 扩展运算符... 文章目录 【ES6.0】- 扩展运算符...一、概述二、拷贝数组对象三、合并操作四、参数传递五、数组去重六、字符串转字符数组七、NodeList转数组八、解构变量九、打印日志十、总结 一、概述 **扩展运算符(...)**允许一个表达式在期望多个参数&#xff0…...

    2024/5/7 1:54:46
  14. 摩根看好的前智能硬件头部品牌双11交易数据极度异常!——是模式创新还是饮鸩止渴?

    文 | 螳螂观察 作者 | 李燃 双11狂欢已落下帷幕&#xff0c;各大品牌纷纷晒出优异的成绩单&#xff0c;摩根士丹利投资的智能硬件头部品牌凯迪仕也不例外。然而有爆料称&#xff0c;在自媒体平台发布霸榜各大榜单喜讯的凯迪仕智能锁&#xff0c;多个平台数据都表现出极度异常…...

    2024/5/7 21:15:55
  15. Go语言常用命令详解(二)

    文章目录 前言常用命令go bug示例参数说明 go doc示例参数说明 go env示例 go fix示例 go fmt示例 go generate示例 总结写在最后 前言 接着上一篇继续介绍Go语言的常用命令 常用命令 以下是一些常用的Go命令&#xff0c;这些命令可以帮助您在Go开发中进行编译、测试、运行和…...

    2024/5/8 1:37:35
  16. 用欧拉路径判断图同构推出reverse合法性:1116T4

    http://cplusoj.com/d/senior/p/SS231116D 假设我们要把 a a a 变成 b b b&#xff0c;我们在 a i a_i ai​ 和 a i 1 a_{i1} ai1​ 之间连边&#xff0c; b b b 同理&#xff0c;则 a a a 能变成 b b b 的充要条件是两图 A , B A,B A,B 同构。 必要性显然&#xff0…...

    2024/5/7 16:05:05
  17. 【NGINX--1】基础知识

    1、在 Debian/Ubuntu 上安装 NGINX 在 Debian 或 Ubuntu 机器上安装 NGINX 开源版。 更新已配置源的软件包信息&#xff0c;并安装一些有助于配置官方 NGINX 软件包仓库的软件包&#xff1a; apt-get update apt install -y curl gnupg2 ca-certificates lsb-release debian-…...

    2024/5/7 16:04:58
  18. Hive默认分割符、存储格式与数据压缩

    目录 1、Hive默认分割符2、Hive存储格式3、Hive数据压缩 1、Hive默认分割符 Hive创建表时指定的行受限&#xff08;ROW FORMAT&#xff09;配置标准HQL为&#xff1a; ... ROW FORMAT DELIMITED FIELDS TERMINATED BY \u0001 COLLECTION ITEMS TERMINATED BY , MAP KEYS TERMI…...

    2024/5/8 1:37:32
  19. 【论文阅读】MAG:一种用于航天器遥测数据中有效异常检测的新方法

    文章目录 摘要1 引言2 问题描述3 拟议框架4 所提出方法的细节A.数据预处理B.变量相关分析C.MAG模型D.异常分数 5 实验A.数据集和性能指标B.实验设置与平台C.结果和比较 6 结论 摘要 异常检测是保证航天器稳定性的关键。在航天器运行过程中&#xff0c;传感器和控制器产生大量周…...

    2024/5/7 16:05:05
  20. --max-old-space-size=8192报错

    vue项目运行时&#xff0c;如果经常运行慢&#xff0c;崩溃停止服务&#xff0c;报如下错误 FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory 因为在 Node 中&#xff0c;通过JavaScript使用内存时只能使用部分内存&#xff08;64位系统&…...

    2024/5/8 1:37:31
  21. 基于深度学习的恶意软件检测

    恶意软件是指恶意软件犯罪者用来感染个人计算机或整个组织的网络的软件。 它利用目标系统漏洞&#xff0c;例如可以被劫持的合法软件&#xff08;例如浏览器或 Web 应用程序插件&#xff09;中的错误。 恶意软件渗透可能会造成灾难性的后果&#xff0c;包括数据被盗、勒索或网…...

    2024/5/8 1:37:31
  22. JS原型对象prototype

    让我简单的为大家介绍一下原型对象prototype吧&#xff01; 使用原型实现方法共享 1.构造函数通过原型分配的函数是所有对象所 共享的。 2.JavaScript 规定&#xff0c;每一个构造函数都有一个 prototype 属性&#xff0c;指向另一个对象&#xff0c;所以我们也称为原型对象…...

    2024/5/7 11:08:22
  23. C++中只能有一个实例的单例类

    C中只能有一个实例的单例类 前面讨论的 President 类很不错&#xff0c;但存在一个缺陷&#xff1a;无法禁止通过实例化多个对象来创建多名总统&#xff1a; President One, Two, Three; 由于复制构造函数是私有的&#xff0c;其中每个对象都是不可复制的&#xff0c;但您的目…...

    2024/5/7 7:26:29
  24. python django 小程序图书借阅源码

    开发工具&#xff1a; PyCharm&#xff0c;mysql5.7&#xff0c;微信开发者工具 技术说明&#xff1a; python django html 小程序 功能介绍&#xff1a; 用户端&#xff1a; 登录注册&#xff08;含授权登录&#xff09; 首页显示搜索图书&#xff0c;轮播图&#xff0…...

    2024/5/8 1:37:29
  25. 电子学会C/C++编程等级考试2022年03月(一级)真题解析

    C/C++等级考试(1~8级)全部真题・点这里 第1题:双精度浮点数的输入输出 输入一个双精度浮点数,保留8位小数,输出这个浮点数。 时间限制:1000 内存限制:65536输入 只有一行,一个双精度浮点数。输出 一行,保留8位小数的浮点数。样例输入 3.1415926535798932样例输出 3.1…...

    2024/5/7 17:09:45
  26. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下&#xff1a;1、长按电脑电源键直至关机&#xff0c;然后再按一次电源健重启电脑&#xff0c;按F8健进入安全模式2、安全模式下进入Windows系统桌面后&#xff0c;按住“winR”打开运行窗口&#xff0c;输入“services.msc”打开服务设置3、在服务界面&#xff0c;选中…...

    2022/11/19 21:17:18
  27. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像&#xff08;每一幅图像的大小是564*564&#xff09; f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...

    2022/11/19 21:17:16
  28. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面&#xff0c;在等待界面中我们需要等待操作结束才能关机&#xff0c;虽然这比较麻烦&#xff0c;但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  29. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows&#xff0c;请勿关闭计算机”的提示&#xff0c;要过很久才能进入系统&#xff0c;有的用户甚至几个小时也无法进入&#xff0c;下面就教大家这个问题的解决方法。第一种方法&#xff1a;我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  30. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题&#xff0c;电脑时发现开机屏幕显现“正在配置Windows Update&#xff0c;请勿关机”(如下图所示)&#xff0c;而且还需求等大约5分钟才干进入系统。这是怎样回事呢&#xff1f;一切都是正常操作的&#xff0c;为什么开时机呈现“正…...

    2022/11/19 21:17:13
  31. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示&#xff0c;没过几秒后电脑自动重启&#xff0c;每次开机都这样无法进入系统&#xff0c;此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一&#xff1a;开机按下F8&#xff0c;在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  32. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况&#xff0c;就是电脑提示正在准备windows请勿关闭计算机&#xff0c;碰到这样的问题该怎么解决呢&#xff0c;现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法&#xff1a;1、2、依次…...

    2022/11/19 21:17:11
  33. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后&#xff0c;每次关机的时候桌面上都会显示一个“配置Windows Update的界面&#xff0c;提示请勿关闭计算机”&#xff0c;每次停留好几分钟才能正常关机&#xff0c;导致什么情况引起的呢&#xff1f;出现配置Windows Update…...

    2022/11/19 21:17:10
  34. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着&#xff0c;别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚&#xff0c;只能是考虑备份数据后重装系统了。解决来方案一&#xff1a;管理员运行cmd&#xff1a;net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  35. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题&#xff1a;电脑提示“配置Windows Update请勿关闭计算机”怎么办&#xff1f;win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢&#xff1f;一般的方…...

    2022/11/19 21:17:08
  36. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 &#xff0c;然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  37. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  38. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了&#xff0c;具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面&#xff0c;长时间没反应&#xff0c;无法进入系统。这个问题原来帮其他同学也解决过&#xff0c;网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  39. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法&#xff0c;并在最后教给你1种保护系统安全的好方法&#xff0c;一起来看看&#xff01;电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中&#xff0c;添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  40. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候&#xff0c;开启电脑发现电脑显示&#xff1a;配置windows更新失败&#xff0c;正在还原更改&#xff0c;请勿关闭计算机。。.这要怎么办呢&#xff1f;下面小编就带着大家一起看看吧&#xff01;如果能够正常进入系统&#xff0c;建议您暂时移…...

    2022/11/19 21:17:02
  41. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机&#xff0c;电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  42. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题&#xff0c;就是我们的win7系统在关机的时候&#xff0c;总是喜欢显示“准备配置windows&#xff0c;请勿关机”这样的一个页面&#xff0c;没有什么大碍&#xff0c;但是如果一直等着的话就要两个小时甚至更久都关不了机&#xff0c;非常…...

    2022/11/19 21:17:00
  43. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时&#xff0c;一般是您正对windows进行升级&#xff0c;但是这个要是长时间没有反应&#xff0c;我们不能再傻等下去了。可能是电脑出了别的问题了&#xff0c;来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  44. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况&#xff0c;当我们打开电脑之后&#xff0c;发现一直停留在一个界面&#xff1a;“配置Windows Update失败&#xff0c;还原更改请勿关闭计算机”&#xff0c;等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  45. 如何在iPhone上关闭“请勿打扰”

    Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...

    2022/11/19 21:16:57