Search code examples
androidmultithreadingrx-java2android-mvvm

Android RxJava Thread Reusal, Is it a bad practice?


I am using retrofit and Rxjava to handle api calls for my mvvm android application. Based on some tutorial, i am currently using RxJava like this.

ViewModel.java

CompositeDisposable disposable = new CompositeDisposable();

private void fetchTodolist(){
        loading.setValue(true);
        disposable.add(
                service.getToDoList("A1833")
                .subscribeOn(Schedulers.newThread())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribeWith(new DisposableSingleObserver<ApiResponse<ArrayList<TodoItem>>>() {

                    @Override
                    public void onSuccess(ApiResponse<ArrayList<TodoItem>> value) {
                        if(value.getStatus() == 200){
                            //on call success code
                        } else {
                            //on call rejected code
                        }
                    }

                    @Override
                    public void onError(Throwable e) {
                        // on call error code
                    }
                })
        );
    }

And now i want to cache the result of the api call on successful call into room database. So i need to use another async method and tried to reuse the new thread i created before. And here's the code.

private void fetchTodolist(){
        loading.setValue(true);
        Scheduler a = Schedulers.newThread();
        disposable.add(
                service.getToDoList("A1833")
                .subscribeOn(a)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribeWith(new DisposableSingleObserver<ApiResponse<ArrayList<TodoItem>>>() {

                    @Override
                    public void onSuccess(ApiResponse<ArrayList<TodoItem>> value) {
                        if(value.getStatus() == 200){

                            a.scheduleDirect(new Runnable() {
                            @Override
                            public void run() {
                                long inserted = dao.insert(value);
                            }

                        });
                        } else {
                            //on call rejected code
                        }
                    }

                    @Override
                    public void onError(Throwable e) {
                        // on call error code
                    }
                })
        );
    }

I wonder if it is a bad practice and will lead to a serious problem. And if so, what's the alternative.


Solution

  • Schedulers uses cached references thus newThread() returns the same Scheduler instance.

    Schedulers.newThread() == Schedulers.newThread()
    

    Generally you should avoid using newThread because it creates a new thread for every application of the operator. So if you run the sequence multiple times, new worker threads are created and dismissed without any kind of reuse. This is especially true for newThread().scheduleDirect which will start a new thread just for that single runnable and stop it afterwards.

    It is recommended you use Schedulers.io() for IO operations so that those underlying worker threads are reused as much as possible later.