Fatal Exception thrown on Scheduler - rxJava2 in Android

1k views Asked by At

I'm introducing myself to rxJava2 in Android with MVP.

For initial steps I have created an Activity, a presenter and a Model objects (every of them with an interface class).

In my activity, I create the presenter, and try to load data, notifying the view when it is ready:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.my_activity);

    MvpPresenter presenter = new Presenter(this,
            AndroidSchedulers.mainThread());

    presenter.loadData();

Inside the presenter, on loadData method, just calling back to view

@Override
public void loadData() {

    compositeDisposable.add(dataRepository.getDataList().
            subscribeOn(Schedulers.io()).
            observeOn(mainScheduler).
            subscribeWith(new DisposableSingleObserver<List<Book>>() {
                @Override
                public void onSuccess(@NonNull List<Book> bookList) {
                    if (!bookList.isEmpty())
                        view.displayBooks(bookList);
                    else
                        view.displayEmpty();
                }

                @Override
                public void onError(@NonNull Throwable e) {
                    view.displayError("boooom");
                }
            }));
    }

Method getBooks() is as follows (I have in mind to use an API, but so far, for simplicity purposes, I just have the data hardcoded)

public Single<List<Shelf>> getShelfList() {
    return Single.fromCallable(new Callable<List<Book>>() {
        @Override
        public List<Book> call() throws Exception {
            Book b1 = new Book();
            Book b2 = new Book();
            Book b3 = new Book();

            List<Book> bookList = Arrays.asList(b1,b2,b3);
            return bookList;
        }
    });
}

The method view.displayBooks(bookList) just have a Toast message (again, for simplicity purposes)

public void displayBooksInShelf(List<Shelf> shelfList) {
        Toast.makeText(this, shelfList.size(), Toast.LENGTH_LONG).show();
    }

Seems very simple and it should the Toast as three books are returned correctly... but when executing, it throws an exception:

java.lang.IllegalStateException: Fatal Exception thrown on Scheduler.
 at io.reactivex.android.schedulers.HandlerScheduler$ScheduledRunnable.run(HandlerScheduler.java:111)
 at android.os.Handler.handleCallback(Handler.java:751)
 at android.os.Handler.dispatchMessage(Handler.java:95)
 at android.os.Looper.loop(Looper.java:154)
 at android.app.ActivityThread.main(ActivityThread.java:6077)
 at java.lang.reflect.Method.invoke(Native Method)
 at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)
 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756)
Caused by: android.content.res.Resources$NotFoundException: String resource ID #0x2
 at android.content.res.Resources.getText(Resources.java:331)
 at android.widget.Toast.makeText(Toast.java:287)

In Unitary Test (Mockito) everything seems to work fine, but together it fails. My suspects are that there is some kind of thread issue. Anybody can help my with this problem?

Also, knowing that I'd like to use retrofit, is the approach I'm using the correct one? Or maybe the thread should be managed in the Model/Repository class?

Hope the information I've provided is enough to clarify where the problem is

Thanks in advance!

1

There are 1 answers

1
Maksim Ostrovidov On BEST ANSWER

Notice this line in the stacktrace:

Caused by: android.content.res.Resources$NotFoundException: String resource ID #0x2

You are trying to access String resource with invalid resource id. Here where it happens:

Toast.makeText(this, shelfList.size(), Toast.LENGTH_LONG).show();

The second argument must be String message or int resource id. You are passing int here, so compiler chooses overload with a resource id (obviously invalid).

If you want to just print int you have to pass String representation of it:

Toast.makeText(this, Integer.toString(shelfList.size()), Toast.LENGTH_LONG).show();