Mathbl
Mathbl

Reputation: 5057

Retrofit 2.0 - Custom CallAdapterFactory - Callbacks not happening on MainThread

I'm in the process of migrating my Android app to Retrofit 2.0. I had a custom ErrorHandler extending RetrofitError so I could react to different Http errors.

Now I understand I must create a custom CallAdapterFactory. I used the sample ErrorHandlingCallAdapter provided here.

My resulting CallAdapter is pretty much the same code, but if needed I could also post my code.

What's happening is that when I use this CallAdapterFactory, callbacks are not happening on the MainThread. I get android.view.ViewRootImpl$CalledFromWrongThreadException when trying to update the UI (which I always need to). I also don't want to always wrap my code with runOnUIThread in my callbacks.

I don't know if this helps, but when I log Thread.currentThread().getName() in my callbacks, it returns OkHttp.

Upvotes: 5

Views: 1301

Answers (2)

Quentin Gaultier
Quentin Gaultier

Reputation: 318

You don't need to create a new executor, you can use retrofit's :

public AuthCall adapt(Call call) {
    return new CustomCall(call, statuses, retrofit.callbackExecutor());
}

keep a reference of it in your adapted calls, and then use it within your callback:

customCall.enqueue(new Callback() {
    executor.execute(...

Upvotes: 1

Mathbl
Mathbl

Reputation: 5057

I ended up passing an executor to my CallAdapter.Factory:

public static class MainThreadExecutor implements Executor {
    private final Handler handler = new Handler(Looper.getMainLooper());

    @Override
    public void execute(@NonNull Runnable r) {
        handler.post(r);
    }
}

...

.addCallAdapterFactory(new ErrorHandlingCallAdapter.ErrorHandlingCallAdapterFactory(new MainThreadExecutor()))

and wrapping the callback in:

callbackExecutor.execute(new Runnable() {
    @Override
    public void run() {
    }
});

I inspired myself from this.

Upvotes: 3

Related Questions