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

Bitmap下载触发UndeliverableException:RxJava与Picasso使用问题

Hey there, let's tackle this UndeliverableException issue you're hitting with RxJava and Picasso in your Fragment. I've dealt with similar problems before, so here's what you need to know and fix:

Why This Happens

UndeliverableException usually pops up when your RxJava subscription (the Disposable) has already been disposed of (like when your Fragment is destroyed), but the asynchronous Picasso image download is still running. When the download finishes, RxJava tries to send the result to a subscriber that no longer exists—hence the exception.

Step-by-Step Solutions

1. Properly Manage Disposable Lifecycle

First, you need to tie your RxJava subscription to your Fragment's lifecycle so it gets cleaned up when the Fragment is destroyed. Use a CompositeDisposable to track all your disposables:

// Declare this as a member variable in your Fragment
private CompositeDisposable mCompositeDisposable = new CompositeDisposable();

// When you create your Observable chain:
Disposable d = mSpinnerSelectionSubject
    .switchMap(selectedItem -> Observable.fromCallable(this::getImageDetails))
    .observeOn(Schedulers.computation())
    .switchMap(imageDetails -> Observable.fromCallable(() -> mPicasso.load(imageDetails.getImagePath()).get()))
    .observeOn(AndroidSchedulers.mainThread())
    // Add your subscriber logic here
    .subscribe(...);

// Add the disposable to the composite
mCompositeDisposable.add(d);

// Clean up in Fragment's onDestroy
@Override
public void onDestroy() {
    super.onDestroy();
    mCompositeDisposable.clear(); // This disposes all tracked subscriptions
}

2. Fix Picasso's Async Handling (Avoid Blocking get())

Using Picasso's get() is a blocking call, which works in computation() but doesn't play nicely with RxJava's cancellation. Instead, use Picasso's async into(Target) and wrap it in an Observable—this lets you cancel the request properly when the disposable is disposed:

// Declare a member variable to hold the Target (Picasso uses weak references, so we need to keep it alive)
private Target mCurrentImageTarget;

// Modify your switchMap for Picasso:
.switchMap(imageDetails -> Observable.create(emitter -> {
    mCurrentImageTarget = new Target() {
        @Override
        public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
            if (!emitter.isDisposed()) {
                emitter.onNext(bitmap);
                emitter.onComplete();
            }
        }

        @Override
        public void onBitmapFailed(Exception e, Drawable errorDrawable) {
            if (!emitter.isDisposed()) {
                emitter.onError(e);
            }
        }

        @Override
        public void onPrepareLoad(Drawable placeHolderDrawable) {
            // Optional: Handle placeholder logic
        }
    };

    // Start the Picasso async load
    mPicasso.load(imageDetails.getImagePath()).into(mCurrentImageTarget);

    // Cancel the Picasso request when the disposable is disposed
    emitter.setCancellable(() -> {
        mPicasso.cancelRequest(mCurrentImageTarget);
        mCurrentImageTarget = null;
    });
}))

3. Add a Global RxJava Error Handler (Safety Net)

As a fallback, you can set a global error handler to catch any stray UndeliverableException and prevent app crashes. Add this in your Application class or early in your app's initialization:

RxJavaPlugins.setErrorHandler(throwable -> {
    if (throwable instanceof UndeliverableException) {
        throwable = throwable.getCause();
    }
    // Log the error instead of letting it crash the app
    Log.e("RxJavaUndeliverable", "Caught undeliverable exception", throwable);
});

This is a last resort—always prioritize fixing the lifecycle and cancellation logic first.

Key Takeaway

The root issue is mismatched lifecycle between your RxJava subscription and the Fragment. By properly disposing subscriptions when the Fragment is destroyed and ensuring Picasso requests are cancelled alongside them, you'll eliminate the UndeliverableException.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 10:41:38