一. android各版本差异性:
6.0 权限:
①.从6.0开始,Android划分了危险权限,比如读取文件,打开摄像头.
②.WiFi相关的操作,需要动态的申请位置权限,如果还想获取WiFi列表,还需要打开GPS位置信息.
7.0
①.fileProvider 应用共享文件.
②.打包apk出现v2
8.0
① 通知,需要创建通知渠道,用户可以根据渠道类型进行屏蔽一些不想要的通知.
② 安装apk去除了"允许安装未知来源"选项.
③ 对从清单文件中静态注册广播增加了限制.
9.0
http明文请求,使用HTTPS加密.
10 深色主题,分区存储. 在特定目录下存储,无需权限,随着安装包卸载,数据自动删除.
11 存储机制更细.位置信息更新.
二. http/socket 通信协议
tcp和utp的区别:
tcp.面向链接,比如拨打电话(先建立链接) ; utp 是无链接,发送数据之前不需要建立链接.
tcp.可靠,稳定.采用三次握手,四次挥手机制,数据可靠,不会重复. UTP 数据不可靠,可能会丢包.
tcp.要求系统资源多 首部开销20个字节 UTP 要求系统少 首部开销 8 个字节.
http是超文本传输协议,为短连接. 客户端发起请求,服务器端接收请求并相应客户端,请求结束之后,主动释放连接,因此为短链接.
请求方式:post,get
get 使用url链接拼接,用 "?" 分割开. 传输数据有限制,不能大于2kb.
post 使用的key value的表单方式发送. 对数据没有限制.
http 和 https 区别:
① 在 Android9.0 之后,需要使用https请求.
② https 需要ca 证书,一般是收费的.
③ http是超文本传输,明文传递. 不安全; https使用具有安全性的ssl加密,安全.
④ http 和 https 是两种不同的链接方式. http端口是80 https端口是443.
socket 是长链接,通常情况下socket链接就是tcp链接.一旦建立,就互相通信.直到双方断开链接.
socket不是一种协议,是一个接口. socket链接至少需要一对套接字 分别是:clientSocket,serviceSocket.连接分为3个步骤:
① 服务器监听: 服务端不清楚具体客户端的套接字,而是出于时刻的监听状态.
② 客户端请求: 客户端携带带有描述服务器套接字,如地址,端口,然后向服务器端发起请求.
③ 链接确认: 服务器端套接字接收到客户端套接字发来的请求后,就响应客户端的请求,并创建一个新的线程,把服务器的套接字描述发给客户端.一旦客户端确认了描述,此时正式建立链接.
而服务器套接字继续监听其他客服端发来的请求.
三. Rxjava+retrofit
rxjava 异步处理数据.obverse观察者订阅obverseable可观察者.通过可观察者对象发射的数据流,在此过程中,可通过操作符 线程切换等操作,最后由观察者做出相应的过程.
retrofit 强大的网络请求. 通过java接口以注解的方式来描述接口信息.并用动态代理的方式生成网络请求的request,然后通过client调用相应的网络框架 默认是okhttp.
四.EventBus
发布订阅模式
对象间一对多依赖关系.当这个对象状态发生改变的时候,其他对象都会接到通知,并自动更新.
在发布订阅模式中,发布者不会直接将信息告诉订阅者,而是通过第三种组件来告知,这样一来,发布和订阅者没有丝毫关系,第三种组件我们称为事件总线,它是发布 订阅关联者,它过滤所有的信息传递给订阅者.
五.消息机制 Handler
由于Android开发规范的限制,我们不能在子线程内更新ui控件.否则就发程序异常崩溃.这个时候就可以使用handler将更新ui的操作切换到主线程中.
为什么子线程不能更新ui?
因为Android的ui控件不是线程安全的,如果在多线程中并发访问可能会导致ui控件处于不可预期的状态,那为什么不加上安全锁呢?
如果加上锁机制的话会让ui访问的逻辑变的更复杂.
其次锁机制会降低ui访问的效率,因为锁机制会阻塞某些线程的执行.
Android的消息机制主要是指Handler的运行机制,handler的运行需要底层的MessageQueue和Looper的支撑.
MessageQueue是消息队列,内部存储了一个消息机制,以队列的方式对外提供插入和删除的工作.但是他不是一个队列.而是采用单链表的数据结构来存储消息列表.MessageQueue只是一个消息存储的单元,不能处理消息.
而Looper就填补了这个功能,looper以无限循环的方式查看是否有新的消息,如果有的话就去处理,没有的话就一直等待.
六.Android 性能优化
①. 布局优化
a.减少布局层次
如果布局中既可以使用相对布局,也可以使用线性布局,那么使用线性布局. 因为相对布局功能比较复杂.
如果布局嵌套那么可以考虑使用相对布局.因为ViewGroup的嵌套就相当于增加了布局的层次,同样会降低程序的性能.
b.使用include标签,这样的话布局可以复用.
②. 绘制优化
避免在view onDraw中创建局部对象,因为onDraw方法可能会频繁的调用,这样的话一瞬间会生成大量对象,不仅占用大量的内存,还会导致系统更加频繁gc,降低了程序的执行效率.
onDraw方法中不要做耗时任务,也不能执行大量的循环操作. 每帧的绘制时间不超过16ms
③. 内存泄露优化
a. 静态变量导致的内存泄露.在dalvik虚拟机中,static变量所指向的内存引用,如果不把它设置为null,GC是永远不会回收这个对象的.
b. 单例模式 其生命周期和application保持一致,因此引用对象无法回收.
c. 属性动画 在Android3.0的时候 Google提供了属性动画, 开启了动画,但没有关闭动画. 虽然在act中界面已经关闭了,动画已经消失了,但是动画一直持有view,而view持有当前的act,最终act无法释放.
④. 响应速度优化
响应速度优化核心就是避免在主线程中做耗时操作,如果避免不了做耗时操作,可以将耗时操作放在线程中.
七.进程间通讯
- Binder
Binder 是 Android 中最核心的 IPC 机制,底层实现基于 Linux 内核:
- AIDL (Android Interface Definition Language):
- 定义客户端和服务端共同遵守的接口
- 自动生成跨进程调用的代码
使用步骤:
1. 创建 AIDL 文件定义接口
2. 实现 Service 并返回 Binder
3. 客户端绑定服务并调用远程方法
-
Messenger
基于 Binder 的轻量级 IPC,适合简单的消息传递 -
ContentProvider 用于跨应用数据共享:
实现 ContentProvider 类并声明于 Manifest
通过 ContentResolver 访问
支持权限控制
- BroadcastReceiver 用于系统范围的事件通知
有序广播 (Ordered Broadcast)
普通广播 (Normal Broadcast)
本地广播 (LocalBroadcastManager,仅进程内)
八. Android WebSocket 即时通讯流程原理
- WebSocket 连接建立流程
1. HTTP 握手阶段:
客户端发送 HTTP Upgrade 请求
服务端返回 101 Switching Protocols 响应
一次握手: 客户端同步标志位,随机生成序列号.
二次握手:服务端初始化自己的序列号,并确认客户端序列号.
三次握手:客户端确认服务端序列号
为什么是三次:
- 防止历史重复连接初始化(旧SYN报文到达时,客户端会拒绝)
- 最少需要三次交互才能确保双方收发能力正常.
序列号的作用:
- 初始值为随机数(安全考虑),
- 后续数据按 seq+payload_len 递增
如客户端发送 seq=100, len=20,则下个报文 seq=120
四次挥手 (连接终止)
1.客户端主动关闭(不再发送数据)
2.服务端确认,但可能还有数据要发送
3.(服务端处理剩余数据...)服务端数据发完后关闭
4.客户端确认
为什么是四次?
- 服务端的 ACK 和 FIN 通常不能合并发送,因为中间可能需要处理剩余数据
- 若服务端无剩余数据,可能合并为三次(Linux 下可通过 tcp_fin_timeout 调整)
2. 协议升级:
成功握手后,TCP 连接保持打开状态
通信协议从 HTTP 切换到 WebSocket 协议
- 2.Android 端实现核心机制
// 状态转换图
[断开] → [连接中] → [已连接] ↔ [数据传输] → [断开中] → [断开]
+----------------+ +----------------+ +-----------------+
| 用户发送消息 | --> | WebSocket发送 | --> | 网络传输 |
+----------------+ +----------------+ +-----------------+
|
+----------------+ +----------------+ +--------v---------+
| 更新本地数据库 | <-- | WebSocket接收 | <-- | 服务器推送 |
+----------------+ +----------------+ +-----------------+
- 关键保活机制
心跳机制原理
客户端每隔N秒发送PING帧 → 服务端回应PONG帧
│___________________________│
超时检测(通常2-3倍间隔)
九.挑战性bug- WebSocket 断线重连的竞态条件
现象:在弱网环境下,重连机制导致多个 WebSocket 实例同时存在,消息重复发送。
难点:
重连逻辑和心跳机制冲突
线程同步问题(主线程和网络线程竞争)
解决方案
// 使用原子变量 + 双重检查锁
private final AtomicBoolean isConnecting = new AtomicBoolean(false);
public void reconnect() {
if (isConnecting.compareAndSet(false, true)) {
try {
if (webSocket != null) {
webSocket.close(1000, "Reconnecting");
}
// 延迟避免频繁重连
handler.postDelayed(() -> {
initWebSocket();
isConnecting.set(false);
}, 2000);
} catch (Exception e) {
isConnecting.set(false);
}
}
}
网友评论