


























WebSocketListener 与 mProxyListener 代理转发写法理解这篇笔记用于理解:在 Android OkHttp WebSocket 封装中,为什么常见写法是内部维护一个 wsListener,同时再保存一个外部传入的 mProxyListener。
核心结论:
OkHttp -> 内部 wsListener -> mProxyListener -> 外部业务逻辑
wsListener 负责封装层统一处理,mProxyListener 负责把事件继续交给业务层。
OkHttp 创建 WebSocket 时,需要传入一个 WebSocketListener:
client.newWebSocket(request, listener)
这个 listener 会在连接打开、收到消息、连接失败、关闭等时机被 OkHttp 回调。
如果你自己封装了一个 WebSocketClient,通常会有两类监听器:
wsListener:封装层内部监听器,真正传给 OkHttp。mProxyListener:外部业务层传入的监听器,保存在封装类内部。也就是说,OkHttp 并不会直接回调业务层的 listener,而是先回调封装层的 wsListener。
完整链路如下:
OkHttp WebSocket 事件
|
v
内部 wsListener
|
| 先做封装层统一逻辑
| 例如日志、状态管理、重连、心跳、线程切换
v
mProxyListener
|
| 再交给外部业务层
v
业务逻辑
所以 mProxyListener 的本质是一个“外部回调出口”。
import android.util.Log
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import okhttp3.WebSocket
import okhttp3.WebSocketListener
import okio.ByteString
class MyWebSocketClient {
companion object {
private const val TAG = "MyWebSocketClient"
}
// 外部业务层注入的 listener。
private var mProxyListener: WebSocketListener? = null
// 内部 listener:真正传给 OkHttp。
private val wsListener: WebSocketListener = object : WebSocketListener() {
override fun onOpen(webSocket: WebSocket, response: Response) {
// 1. 封装层统一逻辑
Log.d(TAG, "connect open")
// 2. 转发给外部业务层
mProxyListener?.onOpen(webSocket, response)
}
override fun onMessage(webSocket: WebSocket, text: String) {
Log.d(TAG, "receive text message")
mProxyListener?.onMessage(webSocket, text)
}
override fun onMessage(webSocket: WebSocket, bytes: ByteString) {
Log.d(TAG, "receive binary message")
mProxyListener?.onMessage(webSocket, bytes)
}
override fun onClosing(webSocket: WebSocket, code: Int, reason: String) {
Log.d(TAG, "connect closing: code=$code, reason=$reason")
mProxyListener?.onClosing(webSocket, code, reason)
}
override fun onClosed(webSocket: WebSocket, code: Int, reason: String) {
Log.d(TAG, "connect closed: code=$code, reason=$reason")
mProxyListener?.onClosed(webSocket, code, reason)
}
override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) {
Log.e(TAG, "connect failure", t)
mProxyListener?.onFailure(webSocket, t, response)
}
}
fun setListener(listener: WebSocketListener?) {
mProxyListener = listener
}
fun connect(client: OkHttpClient, request: Request) {
// OkHttp 实际回调的是内部 wsListener。
client.newWebSocket(request, wsListener)
}
}
业务层只需要传入自己的监听器,实现真正关心的逻辑:
val client = MyWebSocketClient()
client.setListener(object : WebSocketListener() {
override fun onOpen(webSocket: WebSocket, response: Response) {
// 业务逻辑:例如通知 UI 已连接、发送鉴权消息等。
}
override fun onMessage(webSocket: WebSocket, text: String) {
// 业务逻辑:例如解析消息、分发到业务模块等。
}
override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) {
// 业务逻辑:例如提示错误、上报异常等。
}
override fun onClosed(webSocket: WebSocket, code: Int, reason: String) {
// 业务逻辑:例如更新连接状态、释放资源等。
}
})
业务层不需要知道封装层内部如何管理日志、心跳、重连,只需要关心自己的业务事件。
如果直接把外部业务 listener 传给 OkHttp,封装层就失去了统一拦截点。
使用内部 wsListener 再转发给 mProxyListener,可以在转发前后插入通用能力:
try-catch 防御,避免业务回调抛异常影响封装层。因此,这种写法本质上是代理模式或装饰器模式:
外部业务 listener 没有直接交给 OkHttp,
而是被封装层保存起来,
由内部 wsListener 在合适的时候调用它。
super.onXxx(...) 通常有没有必要大多数情况下没有必要。
OkHttp 的 WebSocketListener 默认实现通常是空实现,也就是 no-op:
override fun onOpen(webSocket: WebSocket, response: Response) {
super.onOpen(webSocket, response) // 通常可以省略
}
所以在 Kotlin 或 Java 中,通常可以直接省略 super.onOpen(...)、super.onMessage(...)、super.onFailure(...) 等调用。
可以把 Kotlin/Java 的 listener 理解成 C++ 中保存的一组 callback。
| Kotlin / Java | C++ |
|---|---|
WebSocketListener |
一组回调函数,或一个 listener 接口类 |
object : WebSocketListener() { ... } |
lambda、仿函数、匿名实现 |
mProxyListener |
保存用户传入的 callback 成员变量 |
内部 wsListener 先处理再转发 |
包装一层 callback,先做内部逻辑,再调用用户 callback |
std::function 对照示例#include <functional>
#include <iostream>
#include <string>
struct Callbacks {
std::function<void()> onOpen;
std::function<void(const std::string&)> onMessage;
};
class Client {
Callbacks internal_; // 内部统一入口,相当于 wsListener。
Callbacks proxy_; // 用户注入,相当于 mProxyListener。
public:
Client() {
internal_.onOpen = [this] {
std::cout << "connect open\n"; // 内部统一逻辑。
if (proxy_.onOpen) {
proxy_.onOpen(); // 转发给用户。
}
};
internal_.onMessage = [this](const std::string& message) {
std::cout << "receive message: " << message << '\n';
if (proxy_.onMessage) {
proxy_.onMessage(message);
}
};
}
void setListener(const Callbacks& callbacks) {
proxy_ = callbacks;
}
};
这里的关系和 Kotlin 版本一致:
底层事件 -> internal_ -> proxy_ -> 用户逻辑
mProxyListener 就是业务层 listener 的保存位置。
内部 wsListener 负责拦截 OkHttp 的回调,先做封装层通用逻辑,再调用 mProxyListener,把事件转发给外部业务层。
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。