You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何捕获Firebase中Android Apollo GraphQL SDK抛出的IllegalStateException

问题
  • 自有代码库无法捕获Firebase平台追踪到的、由2.5.12版本Android Apollo GraphQL SDK引发的崩溃,暂未复现问题
  • 异常表现和aws-mobile-appsync-sdk-android仓库153号issue记录的问题相似,但该issue归属RealAppSync项目而非Apollo
  • 核心疑问:Apollo采用回调机制的前提下,是否可以在业务代码层捕获并处理该IllegalStateException
  • 异常堆栈如下:
Fatal Exception: java.lang.IllegalStateException
Found: TERMINATED, but expected [ACTIVE, CANCELED]

com.apollographql.apollo.internal.RealApolloCall.responseCallback (RealApolloCall.java:367)
com.apollographql.apollo.internal.RealApolloCall$1.onFetch (RealApolloCall.java:287)
com.apollographql.apollo.internal.fetcher.CacheFirstFetcher$CacheFirstInterceptor$1.onFetch (CacheFirstFetcher.java:48)
com.apollographql.apollo.internal.interceptor.ApolloCacheInterceptor$1.run (ApolloCacheInterceptor.java:60)
java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1167)
java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:641)
java.lang.Thread.run (Thread.java:923)
回答

直接在业务层的Apollo请求回调里加try-catch,捕获不到这个异常。
这个异常抛出在Apollo SDK内部的线程池工作线程中,触发时机早于回调分发逻辑:SDK在执行responseCallback时会先校验当前Call的状态,发现状态已经是TERMINATED、不符合回调执行要求时直接抛出异常,根本不会走到你实现的onResponse/onFailure回调里,自然也无法通过回调层的代码捕获。

可以通过以下两种可行方案兜底处理:

1. 自定义Apollo调度器做异常拦截

构建Apollo客户端时,传入自定义的线程调度器,在调度器层面给所有执行的任务套一层try-catch,匹配到该特征异常时直接拦截不上抛,示例代码:

// 包装原有默认调度器,增加异常捕获逻辑
val originalDispatcher = ApolloClient.defaultDispatcher()
val safeDispatcher = Executor { command ->
    originalDispatcher.execute {
        try {
            command.run()
        } catch (e: IllegalStateException) {
            // 匹配该异常的固定特征,避免误拦其他异常
            if (e.message?.startsWith("Found: TERMINATED, but expected") == true) {
                // 这里可以加自定义埋点统计异常触发频次,不向上抛即可避免崩溃
                return@execute
            }
            throw e
        }
    }
}

val apolloClient = ApolloClient.builder()
    .serverUrl(API_ENDPOINT)
    // 省略其他原有配置
    .dispatcher(safeDispatcher)
    .build()

2. 全局未捕获异常兜底

如果不想修改Apollo客户端初始化逻辑,可以在应用自定义的全局UncaughtExceptionHandler中增加异常特征匹配,识别到是该类Apollo状态异常时,直接拦截终止崩溃流程,注意不要影响其他正常异常的上报和处理。

以上两种都是临时兜底方案,该问题的根因是Apollo 2.x版本的Call状态流转存在竞态:请求已经结束进入TERMINATED状态后,CacheFirst策略下的缓存读取异步回调才返回,触发状态校验失败抛异常。如果升级成本可控,直接升级到Apollo 3.x版本即可从根源解决,3.x重构了Call状态管理逻辑,不存在该竞态问题。

内容的提问来源于stack exchange,提问作者Peter Williams

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 14:09:18