我应该在哪里捕获 FirestorePagingAdapter - FirebaseUI-Android 抛出的 InterruptedException

问题描述 投票:0回答:2

根据 Firebase Crashlytics,我的一些用户遇到了崩溃:

Fatal Exception: io.reactivex.rxjava3.exceptions.UndeliverableException: The exception could not be delivered to the consumer because it has already canceled/disposed the flow or the exception has nowhere to go to begin with. Further reading: https://github.com/ReactiveX/RxJava/wiki/What's-different-in-2.0#error-handling | java.lang.InterruptedException
   at io.reactivex.rxjava3.plugins.RxJavaPlugins.onError(RxJavaPlugins.java:2)
   at io.reactivex.rxjava3.internal.operators.single.SingleFromCallable.subscribeActual(SingleFromCallable.java:54)
   at io.reactivex.rxjava3.core.Single.subscribe(Single.java:8)
   at io.reactivex.rxjava3.internal.operators.single.SingleSubscribeOn$SubscribeOnObserver.run(SingleSubscribeOn.java:2)
   at io.reactivex.rxjava3.core.Scheduler$DisposeTask.run(Scheduler.java:9)
   at io.reactivex.rxjava3.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:13)
   at io.reactivex.rxjava3.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java)
   at java.util.concurrent.FutureTask.run(FutureTask.java:266)
   at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301)
   at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
   at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
   at java.lang.Thread.run(Thread.java:923)

Caused by java.lang.InterruptedException
   at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedInterruptibly(AbstractQueuedSynchronizer.java:1024)
   at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(AbstractQueuedSynchronizer.java:1334)
   at java.util.concurrent.CountDownLatch.await(CountDownLatch.java:232)
   at com.google.android.gms.tasks.zzaa.zza(zzaa.java:2)
   at com.google.android.gms.tasks.Tasks.await(Tasks.java:28)
   at com.firebase.ui.firestore.paging.FirestorePagingSource.lambda$loadSingle$0(FirestorePagingSource.java)
   at com.firebase.ui.firestore.paging.FirestorePagingSource.$r8$lambda$aRsAFsiduxRWbX-Rs8tsd39JsV0(FirestorePagingSource.java)
   at com.firebase.ui.firestore.paging.FirestorePagingSource$$InternalSyntheticLambda$0$301762c7c2c4bb9cc6676b1600ffb92473af44448cde26854aae0b3e15f6f4f6$0.call$bridge(FirestorePagingSource.java:92)
   at io.reactivex.rxjava3.internal.operators.single.SingleFromCallable.subscribeActual(SingleFromCallable.java:16)
   at io.reactivex.rxjava3.core.Single.subscribe(Single.java:8)
   at io.reactivex.rxjava3.internal.operators.single.SingleSubscribeOn$SubscribeOnObserver.run(SingleSubscribeOn.java:2)
   at io.reactivex.rxjava3.core.Scheduler$DisposeTask.run(Scheduler.java:9)
   at io.reactivex.rxjava3.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:13)
   at io.reactivex.rxjava3.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java)
   at java.util.concurrent.FutureTask.run(FutureTask.java:266)
   at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301)
   at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
   at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
   at java.lang.Thread.run(Thread.java:923)

我无法重现该错误。但是,在错误消息中链接的进一步阅读中,我可以阅读以下内容,这似乎与我的问题相关:

此外,一些第三方库/代码在获取时会抛出异常 被取消/处置调用中断,导致无法送达 大多数时候都是例外。 2.0.6 中的内部变化现在一致 在此之前取消或处置订阅/可处置 取消/处置任务或工作人员(这会导致中断 目标线程)。

// in some library
try {
   doSomethingBlockingly()
} catch (InterruptedException ex) {
   // check if the interrupt is due to cancellation
   // if so, no need to signal the InterruptedException
   if (!disposable.isDisposed()) {
      observer.onError(ex);
   }
}

如果库/代码已经这样做了,则无法交付 InterruptedExceptions 现在应该停止。如果这个模式不是 以前使用过,我们鼓励更新有问题的代码/库。

下面是我使用 FirebaseUI-Android 设置 FirestorePagingAdapter 的代码。如前所述,它非常适合除少数用户之外的所有用户。

com.google.firebase.firestore.Query feedBaseQuery = firebaseHelper.getFeedBaseQuery();
    PagingConfig config = new PagingConfig(10, 5, false);
    FirestorePagingOptions<FeedObject> options = new FirestorePagingOptions.Builder<FeedObject>()
            .setLifecycleOwner(mainActivity)
            .setQuery(feedBaseQuery, config, FeedObject.class)
            .build();
    this.feedAdapter = new FirestoreFeedAdapter(mainActivity, options);
    recyclerView.setHasFixedSize(false);
    recyclerView.setLayoutManager(new LinearLayoutManager(mainActivity));
    recyclerView.setAdapter(this.feedAdapter);

所以,我现在最好的猜测是应用程序在从 Firestore 检索数据时以某种方式被中断,这会引发从未捕获的 InterruptedException。我想我的问题是我是否应该以及在哪里捕获 InterruptedException?

android firebase firebaseui crashlytics-android
2个回答
1
投票

当我在非常糟糕的网络或离线模式下快速更改片段时,我遇到了同样的错误,不太好,但我将其添加到我的应用程序类中。而且效果很好...

RxJavaPlugins.setErrorHandler { e ->
    if (e is UndeliverableException) {
        Log.d(TAG, e.toString())
    } else {
        Thread.currentThread().also { thread ->
            thread.uncaughtExceptionHandler.uncaughtException(thread, e)
        }
    }
}

0
投票

根据RxJava文档(https://github.com/ReactiveX/RxJava/wiki/What's- Different-in-2.0#error-handling),处理RxJava异常的推荐方法如下:

  1. 在应用程序的

    handleRxJava3Error()
    方法中实现
    onCreate
    方法。

  2. 确保导入必要的依赖项。

注意以下两个导入。

// For RxJava3
import io.reactivex.rxjava3.exceptions.UndeliverableException
import io.reactivex.rxjava3.plugins.RxJavaPlugins

// For RxJava2
import io.reactivex.exceptions.UndeliverableException
import io.reactivex.plugins.RxJavaPlugins

RxJava2 和 RxJava3 的 errorHandler 机制是相同的。但进口的就不一样了。不知道为什么他们会发展成这样。

import android.content.Context
import io.reactivex.rxjava3.exceptions.UndeliverableException
import io.reactivex.rxjava3.plugins.RxJavaPlugins
import java.io.IOException
import java.net.SocketException

fun Context.handleRxJava3Error() {
    RxJavaPlugins.setErrorHandler { error ->
        var e = error
        if (e is UndeliverableException) {
            e = e.cause ?:let { e }
        }
        if (e is IOException || e is SocketException) {
            // Fine, irrelevant network problem or API that throws on cancellation
            return@setErrorHandler
        }
        if (e is InterruptedException) {
            // Fine, some blocking code was interrupted by a dispose call
            return@setErrorHandler
        }
        if (e is NullPointerException || e is IllegalArgumentException) {
            // This likely a bug in the application
            Thread.currentThread().uncaughtExceptionHandler
                ?.uncaughtException(Thread.currentThread(), e)
                ?: logWarn(e.message)
            return@setErrorHandler
        }
        if (e is IllegalStateException) {
            // This is a bug in RxJava or in a custom operator
            Thread.currentThread().uncaughtExceptionHandler
                ?.uncaughtException(Thread.currentThread(), e)
                ?: logWarn(e.message)
            return@setErrorHandler
        }

        logWarn(e.message)
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.