OkHttpClient 最稳:回调在后台线程、自带连接池与DNS缓存、异步建连;Java-WebSocket易卡主线程且需手写重连;AndroidAsync已停更且TLS1.3兼容差。

用 OkHttpClient 建立 WebSocket 连接最稳,Java-WebSocket 容易卡主线程、AndroidAsync 已停止维护 —— 别踩这两个坑。
选 OkHttp 还是 Java-WebSocket?看这三点
选库不是看文档多不多,是看它怎么处理异常、线程和重连:
-
OkHttpClient:所有回调都在后台线程,onMessage不会阻塞 UI;自带连接池和 DNS 缓存;newWebSocket()返回即异步启动,不阻塞调用方 -
Java-WebSocket:默认使用connectBlocking()会卡死主线程(哪怕你在子线程调用,它内部仍可能抛IllegalThreadStateException);心跳、重连得自己手写,容易漏掉onError中的断连兜底 -
AndroidAsync:最新版停留在 2019 年,websocket()方法在 Android 12+ 上因 TLS 1.3 兼容问题频繁报javax.net.ssl.SSLHandshakeException
OkHttp WebSocket 必须配的三件事
只写 client.newWebSocket(request, listener) 肯定连不上,漏掉任一都会静默失败:
Android 开发调试技能,通过系统 ADB 工具操作 Android 设备。以下场景必须触发此技能:(1) 直接 ADB 操作——安装 APK、查看设备列表、抓取 logcat 日志、查看已安装应用、清除应用数据、截图、重启设备、拉取/推送文件、查看 CPU/内存/电池信息、adb shell 操作;(2)...
- Manifest 里必须有
<uses-permission android:name="android.permission.INTERNET"/>—— 没它连ws://都会直接抛IOException: Cleartext HTTP traffic not permitted - URL 必须用
ws://或wss://,不能写成http://;如果后端是 Nginx 反代,确保配置了proxy_http_version 1.1和proxy_set_header Upgrade $http_upgrade -
WebSocketListener的onFailure里必须手动触发重连逻辑 —— OkHttp 不自动重连,且onClose不代表连接断开(比如网络闪断时只走onFailure)
发送消息前先确认连接状态
webSocket.send() 不会校验连接是否存活,发出去就丢,服务器收不到也不报错:
- 每次发消息前查
webSocket.isClosed() == false && webSocket.isClosing() == false,否则直接跳过 - 别依赖
onOpen后就“一定可用”——某些弱网场景下onOpen触发后几毫秒内连接就断了,但onClose还没来得及回调 - 文本消息建议加简单校验:
if (text != null && !text.trim().isEmpty()) webSocket.send(text),避免空字符串触发服务端解析异常
心跳和重连不能只靠 onOpen/onClose
真实网络环境里,NAT 超时、运营商劫持、WiFi 切换都会让连接“假活”——看起来没断,其实发包已丢:
- 心跳必须用
webSocket.send()发真实帧(比如"ping"),不能只靠PingFrame—— 多数安卓设备的底层 WebSocket 实现不转发 Ping/Pong 帧给应用层 - 重连间隔要指数退避:
1s → 2s → 4s → 8s,避免瞬间重连风暴打崩服务器 - 重连前清掉旧
webSocket引用并调webSocket.cancel(),否则旧连接残留可能占用 socket fd 导致IOException: Too many open files
真正难的不是连上,是连上之后怎么判断“它还活着”。很多崩溃日志里出现的 NullPointerException 都是因为在 onFailure 里没及时置空 webSocket 引用,结果定时心跳还在往一个已销毁的对象发消息。

















