Android Kotlin+Flow使用Apollo 3 GraphQL订阅网络异常优雅处理方案
问题根因
你遇到的java.lang.IllegalStateException: WebSocket queue full异常属于Apollo3 WebSocket引擎内部抛出的未托管异常,触发场景是开启飞行模式后WebSocket连接已失效,Apollo内部尝试发送停止订阅的控制帧时,WebSocket写入队列已满无法写入,该异常没有被传递到订阅返回的Flow消费链中,因此你在execute()返回的Flow后添加的catch操作符无法捕获。
解决方案
1. 配置WebSocket全局异常处理器(必选)
Apollo3的WebSocketNetworkTransport提供了专门的webSocketErrorHandler参数,所有WebSocket层抛出的异常都会回调到该处理器,你可以在这里捕获异常避免崩溃:
ApolloClient.Builder() .networkTransport( WebSocketNetworkTransport( serverUrl = baseUrl, webSocketErrorHandler = { throwable -> // 按需处理异常,不需要抛出即可避免应用崩溃 if (throwable is IllegalStateException && throwable.message?.contains("WebSocket queue full") == true) { // 可添加埋点日志上报这类异常,不影响业务运行 } // 其他WebSocket异常也可在这里统一处理 } ) ).build()
2. 调大WebSocket队列容量(可选优化)
如果你的业务场景会短时间发送大量WebSocket帧,可以主动调大队列上限,默认队列大小为64,可根据业务需要调整:
// 自定义OkHttp WebSocket引擎,设置更大的队列容量 val customWsEngine = OkHttpWebSocketEngine( webSocketFactory = OkHttpClient().newWebSocketFactory(), maxQueueSize = 256 ) // 传入自定义引擎到WebSocket传输配置 WebSocketNetworkTransport( serverUrl = baseUrl, engine = customWsEngine, webSocketErrorHandler = { /* 异常处理逻辑 */ } )
3. 主动监听网络状态管理订阅生命周期(可选优化)
在Android端注册网络状态监听,当检测到网络断开(如飞行模式开启)时,主动取消订阅Flow的收集任务,避免Apollo内部向已失效的连接写入控制帧:
// 示例:在ViewModel中使用生命周期作用域收集订阅 viewModelScope.launch { apolloClient.subscribe(ProfileSubscription()).execute() .catch { /* 这里可以捕获业务层的订阅异常 */ } .collect { subscriptionData -> // 处理订阅返回的更新数据 } } // 网络断开时取消对应作用域,即可自动终止订阅,避免无效写入
4. 升级Apollo依赖版本(可选)
该类WebSocket未捕获异常的问题在Apollo 3.7.0及以上版本已经做了默认兼容处理,内部会自动捕获写入异常不会直接抛出导致崩溃,如果你的项目允许升级依赖,可以优先升级到最新稳定版解决。
内容的提问来源于stack exchange,提问作者kingston
相关产品推荐
相关产品推荐

