GoogleApiClient:多线程Android应用程序中的“结果已被使用”

Posted

技术标签:

【中文标题】GoogleApiClient:多线程Android应用程序中的“结果已被使用”【英文标题】:GoogleApiClient: "Result has already been consumed" in multi-thread Android app 【发布时间】:2016-03-20 19:47:10 【问题描述】:

最好的处理方法是什么

java.lang.IllegalStateException: Result has already been consumed.
    at com.google.android.gms.common.internal.zzx.zza(Unknown Source)
    at com.google.android.gms.internal.zzly.await(Unknown Source)
    at com.google.android.gms.internal.zzmo.await(Unknown Source)
    at com.google.android.gms.internal.zzmo.get(Unknown Source)

当使用来自不同线程的两个不同 GoogleApiClients 时会发生什么情况?

我有一个 MainActivity,onStart() 构建一个新的 GoogleApiClient 实例,然后调用

OptionalPendingResult<GoogleSignInResult> opr = 
    GoogleSignInApi.silentSignIn(googleApiClient);
opr.setResultCallback(myCallback);

同时,Activity 启动了一个 IntentService(用于刷新 GCM 令牌),它也构建了一个新的 GoogleApiClient 实例,并调用

OptionalPendingResult<GoogleSignInResult> opr = 
    GoogleSignInApi.silentSignIn(googleApiClient);
opr.await(); // Blocks
return opr.get();

异常发生在opr.get() 调用上。似乎 GoogleApiClient 在某处共享它的资源,并且创建它的新实例并不能让我从管理一些跨线程状态中解脱出来。

当您需要两次时,您使用 GoogleApiClient 的方法是什么?

保持 ApiClient 的静态持有者? 保持共享的原子引用,例如“我们现在正在连接,请保持”? 对 GoogleApiClient 有一些包装?

更新

MainActivity 需要 GoogleApiClient 来确保用户已登录,如果未登录则显示提示。

IntentService 实际上只需要 GoogleSignInAccount 来获取 OAuth 令牌。但是为了确保令牌仍然是新鲜的,它使用 GoogleApiClient 获取一个新鲜的帐户。因此,也许将 GoogleSignInAccount 存储在某个共享商店中也会有所帮助。但是我怎么知道它是否还新鲜呢?

【问题讨论】:

两个GoogleApiClient-s几乎相同,不同的是Activity有enableAutoManage(this, this),而IntentService自己调用connect()/disconnect()。 【参考方案1】:

其实opr.await()已经消耗资源并返回。应该是

OptionalPendingResult<GoogleSignInResult> opr = 
    GoogleSignInApi.silentSignIn(googleApiClient);
return opr.await(); // Blocks

【讨论】:

以上是关于GoogleApiClient:多线程Android应用程序中的“结果已被使用”的主要内容,如果未能解决你的问题,请参考以下文章

GoogleApiClient 在调用 onConnected 函数后抛出“GoogleApiClient 尚未连接”

为啥使用 GoogleAPIClient 请求位置更新?

GoogleApiClient.isConnected() 在飞行模式下返回 true

强制关闭 GoogleApiClient.connect()

使用 GoogleApiClient 静默登录以检索令牌

onCreate 与 onStart 中的 GoogleAPIClient 连接