基于开源网络框架实现网络请求方案有利有弊,可以根据实际需要选择合适的开源网络框架。
2.2 基于系统方法
基于系统方法实现的网络请求方案通常采用 HttpURLConnection 或 HttpClient:
-
HttpURLConnection:在 JDK 的 java.net 包提供的一种多用途、轻量级的访问 HTTP 协议的基本功能类,大多数的应用程序都使用该接口进行网络访问请求;
-
HttpClient:是 Apache 开源组织提供的网络访问类,封装了 HTTP 协议的细节实现,Android 6.0 之前包含在系统 API 中。
它们都提供较多的 API,而且相对比较稳定。这两种网络请求类均有以下功能:
在 Android 6.0 之前大多数应用的网络请求是通过 HttpClient 实现的,相比较于 HttpURLConnection ,使用 HttpClient 具有以下优势:
-
从易用性方面对比:HttpClient 封装了 HTTP 协议的细节,使用起来比较方便。HttpURLConnection 是 Java 的标准类,由于缺少封装导致使用不便;
-
从稳定性方面对比:HttpClient 功能强大且更稳定,容易控制细节。而之前的 HttpURLConnection 一直存在着版本兼容的问题。
从 Android 6.0 开始移除了 HttpClient,如果在 Android 6.0 以上继续使用 HttpClient 时,需要在相应的 module下的 build.gradle 中进行依赖库配置。具体配置如下:
android {
useLibrary ‘org.apache.http.legacy’
}
因此,Android 6.0 以上,更推荐使用 HttpURLConnection。从上述的分析可以看出:之前一直使用 HttpClient 是由于 HttpURLConnection 不稳定导致的。目前谷歌已经修复了 HttpURLConnection 存在的一些问题,相比 HttpClient 优势如表 2-1 所示:
表 2-1 HttpURLConnection 与 HttpClient 功能对比
因此,使用基于系统方法实现的网络请求方案一般采用 HttpURLConnection 来实现。
============================================================================
如果 SDK 网络模块基于开源网络框架实现,可维护性和版本控制都有一定的风险,此外还会导致 SDK 体积增大很多。由于这些缺点很难被用户所接受,因此基于开源网络框架实现网络模块不适用于 SDK。
考虑到上述原因,SDK 网络模块最终采用了基于 HttpURLConnection 的方式实现。
HttpURLConnection 是系统提供的网络访问 API,不仅可满足 SDK 网络请求的需要,而且系统 API 功能更稳定,更易扩展。
3.1.1 实现原理
Android 中进行网络请求是基于 HTTP 协议实现的。HTTP 协议是目前 Internet 上最常使用、最重要的协议,该协议为典型的请求 - 响应模型:
-
客户端建立连接并发送请求;
-
服务端接受并处理请求;
-
服务端发送应答;
-
客户端接受并处理应答。
在基于 HttpURLConnection 实现网络请求方案时,很有必要对 HttpURLConnection 有进一步的了解。HttpURLConnection 继承自 URLConnection 抽象类,URLConnection 类本身依赖于 Socket 类实现网络连接。Socket 又称做套接字,它把复杂的网络操作抽象为简单的接口供上层调用。由于 HttpURLConnection 并不是底层的连接,而是在底层连接上的一个请求,因此 HttpURLConnection 不需要设置 Socket。
HttpURLConnection 支持 GET、POST、PUT、DELETE 等请求方式,最常用的就是 GET 与 POST 请求,下面从数据传输长度和安全性两方面对比:
-
数据传输长度:一般来说, GET 请求传输的数据长度有限制(URL 有长度限制),POST 请求传输的数据长度没有限制;
-
安全性:GET 请求安全性较差(发送的数据会拼接在 URL 后面),POST 请求相对安全(数据不显示在 URL 中)。
考虑到 SDK 采集的数据量相对较大,且对数据安全性要求较高,因此采用 HttpURLConnection POST 方式实现网络请求。
3.1.2 使用方式
HttpURLConnection 的具体使用步骤如图 3-1 所示:
图 3-1 HttpURLConnection 使用流程
由于涉及到网络访问,需要在 Manifest 文件中添加网络访问权限:
以上是对 HttpURLConnection 的原理以及具体使用的介绍,下面对 SDK 中网络请求的具体实现进行介绍。
3.2.1 网络相关配置
SDK 可以对数据上报进行一系列的配置,开发者可根据 App 的特点设置相应的配置,从而达到最高效的数据上报效果。SDK 的相关配置在初始化时完成,可以配置的参数如下:
mServerUrl:数据上报地址,采集的本地数据将上报到该地址; mFlushInterval:两次数据发送的最小时间间隔(单位毫秒),默认值为 15; mFlushBulkSize:本地缓存数据的最大条目数,当本地缓存条数达到 mFlushBulkSize 则会上报数据, 默认值为 100; mNetworkTypePolicy:网络上传策略,可配置为 3G、4G、5G、WIFI 等网络类型进行上报。
3.2.2 工作线程封装
SDK 数据上报是在子线程中完成的,当采集的数据满足上报策略时触发数据异步上报,上传任务的管理调度在 Worker 类中完成。在 Worker 初始化时,创建 HandlerThread 实例,HandlerThread 本质上是一个线程类,它继承自 Thread 类。HandlerThread 内有自己的 Looper 对象,可以进行 Looper 循环。通过获取 HandlerThread 中 Looper 对象传递给 Handler 对象,可以在 handleMessage 方法中执行异步任务。
AnalyticsMessageHandler 继承自 Handler,在 handleMessage 中接收 Worker 发送的消息并执行数据上报或删除。
在 HandlerThread 中的 Looper 对象,传递给 AnalyticsMessageHandler 对象,在 handleMessage 方法中实现异步网络任务。AnalyticsMessageHandler 代码实现如下:
private class AnalyticsMessageHandler extends Handler {
…
Worker() {
final HandlerThread thread =
new HandlerThread(“com.sensorsdata.analytics.android.sdk.AnalyticsMessages.Worker”,
Thread.MIN_PRIORITY);
thread.start();
mHandler = new AnalyticsMessageHandler(thread.getLooper());
}
@Override
public void handleMessage(Message msg) {
…
if (msg.what == FLUSH_QUEUE) {
sendData();
} else if (msg.what == DELETE_ALL) {
try {
mDbAdapter.deleteallEvents();
} catch (Exception e) {
com.sensorsdata.analytics.android.sdk.SALog.printstacktrace(e);
}
} else {
SALog.i(TAG, "Unexpected message received by SensorsData worker: " + msg);
}
…
}
…
}
Worker 中封装了两个方法 runMessage 和 runMessageOnce :
Handler 中的 sendMessageDelayed() 方法可以实现数据的延时上报。
3.2.3 数据上报策略
在 SDK 数据存储解析中介绍了数据的采集与存储策略:采集的数据会先保存到本地,符合上报策略才会上报。
- 客户端本地存储的数据超过一定条数时(默认 100 条)会上报数据
在 SDK 初始化时,可配置 mFlushBulkSize 参数来控制条数限制。如果不进行设置,则默认为 100 条。如果用户设置的条数小于 50 条,则默认为 50 条。SDK 采集的数据较多,如果设置上报条数太小会导致频繁的网络请求(上报数据),从而影响性能。如果用户设置上报条数过多,会导致一次上传的数据过大,这样不仅会导致上传时间长还很可能会出现上传失败的情况。如果没有特殊要求,可直接使用默认值。
- 数据采集后间隔一定时间(默认 15 秒)会上报数据
在 SDK 初始化时,可配置 mFlushInterval 参数来控制时间间隔限制。如果不满足上报条数限制时,SDK 会执行一个延时任务,延时 mFlushInterval 设定的时间后执行。
总结
首先是感觉自己的基础还是不够吧,大厂好像都喜欢问这些底层原理。
另外一部分原因在于资料也还没有看完,一面时凭借那份资料考前突击恶补个几天居然也能轻松应对(在这里还是要感谢那份资料,真的牛),于是自我感觉良好,资料就没有怎么深究下去了。
之前的准备只涉及了Java、Android、计网、数据结构与算法这些方面,面对面试官对其他基础课程的考察显得捉襟见肘。
下一步还是要查漏补缺,进行针对性复习。
最后的最后,那套资料这次一定要全部看完,是真的太全面了,各个知识点都涵盖了,几乎我面试遇到的所有问题的知识点这里面都有!在这里也免费分享给大家,希望大家不要犯和我一样的错误呀!!!一定要看完!
643775476906)]
[外链图片转存中…(img-wykUCeS7-1643775476907)]
[外链图片转存中…(img-AdXbUHxL-1643775476907)]
获取方式:点击我的GitHub
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。