为什么在调用Wearable.getMessageClient时出现ConcurrentModificationExce



这看起来像是Google Wearable API中的并发错误,但如果我错了,请告诉我,并提出解决方法。此代码的目的是获得一个可穿戴消息客户端,并向WearOS设备发送消息。

我需要异步执行,以避免锁定主线程。看起来谷歌对getMessageClient的实现不是线程安全的。我应该锁定一些对象以避免崩溃吗?这里最好的方法是什么?为什么谷歌不能以线程安全的方式添加回调?

IMO,他们所需要做的就是在"锁定"之前锁定SimpleArrayMap对象;放入";被调用并在"之后释放;放入";完成。

fun sendToWear(msg:String) {
lifecycle.coroutineScope.launch {
withContext(Dispatchers.IO) {
val nodeListTask = Wearable.getNodeClient(applicationContext).getConnectedNodes()
try {
val nodes = Tasks.await<List<Node>>(nodeListTask)
Tasks.await<List<Node>>(nodeListTask, 10, TimeUnit.SECONDS)
for (node in nodes) {
//Send the message///
val sendMessageTask = Wearable.getMessageClient(this@RootActivity).sendMessage(node.getId(),
BROADCAST_PATH, msg.toByteArray())

堆栈跟踪:

java.util.ConcurrentModificationException: 
at androidx.collection.SimpleArrayMap.put (SimpleArrayMap.java:482)
at com.google.android.gms.common.api.internal.zzc.addCallback (zzc.java:20)
at com.google.android.gms.common.api.internal.zaae.<init> (zaae.java:14)
at com.google.android.gms.common.api.internal.zaae.zaa (zaae.java:5)
at com.google.android.gms.common.api.GoogleApi.<init> (GoogleApi.java:31)
at com.google.android.gms.wearable.MessageClient.<init> (MessageClient.java:3)
at com.google.android.gms.wearable.internal.zzez.<init> (zzez.java:4)
at com.google.android.gms.wearable.Wearable.getMessageClient (Wearable.java:11)
at info.gryb.gac.mobile.fragments.RootActivity$sendToWear$1$1.invokeSuspend (RootActivity.kt:1048)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith (ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run (Dispatched.kt:241)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely (CoroutineScheduler.kt:594)
at kotlinx.coroutines.scheduling.CoroutineScheduler.access$createdWorkers (CoroutineScheduler.kt:60)
at kotlinx.coroutines.scheduling.CoroutineScheduler.access$runSafely (CoroutineScheduler.kt:60)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run (CoroutineScheduler.kt:740)

它在尝试通过调用"来添加回调时崩溃put";在下面的谷歌API代码中:

public final void addCallback(String var1, @NonNull LifecycleCallback var2) {
if (!this.zzbe.containsKey(var1)) {
this.zzbe.put(var1, var2); <-- Crashes in this put
if (this.zzbf > 0) {
(new zze(Looper.getMainLooper())).post(new zzd(this, var2, var1));
}
} else {
throw new IllegalArgumentException((new StringBuilder(59 + String.valueOf(var1).length())).append("LifecycleCallback with tag ").append(var1).append(" already added to this fragment.").toString());
}
}

它绝对值得作为一个bug提出,无论是为了修复并发性,还是为了更清晰的文档。

但是MessageClient api都是异步的,它们在可用时返回指示结果的Task,因此似乎不需要在IO Dispatcher上运行这些api。

您还应该能够使用org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.5.2来使用kotlin友好的等待方法。

val nodeList = Wearable.getNodeClient(applicationContext).getConnectedNodes().await()

所以

相关内容

  • 没有找到相关文章

最新更新