RxJava subscribeOn and onserveOn thread switching records

Comparisons and analysis through several examples

  • 1. Do not use subscribeOn and observeOn
public class RxJavaDemoActivity extends BasicActivity{

    @Override
    protected void onCreate( Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_rxjavamain);
        test4();

    }

    private void test4() {
        Log.i("test0",Thread.currentThread().getName().toString() + " ,id = "+Thread.currentThread().getId());
        Observable.create(new Observable.OnSubscribe<Integer>() {
            @Override
            public void call(Subscriber<? super Integer> subscriber) {
                Log.i("test1",Thread.currentThread().getName().toString() + " ,id = "+Thread.currentThread().getId());
                subscriber.onNext(R.drawable.picasso_drawable);
            }
        })
        .map(new Func1<Integer, Drawable>() {
            @Override
            public Drawable call(Integer integer) {
                Log.i("test2",Thread.currentThread().getName().toString() + " ,id = "+Thread.currentThread().getId());
                Drawable drawable = getResources().getDrawable(integer);
                return drawable;
            }
        })
        .subscribe(new Subscriber<Drawable>() {
            @Override
            public void onCompleted() {}

            @Override
            public void onError(Throwable e) {}

            @Override
            public void onNext(Drawable drawable) {
                Log.i("test3",Thread.currentThread().getName().toString() + " ,id = "+Thread.currentThread().getId());
            }
        });
    }
}    

The output results are as follows:

08-17 09:06:14.028 8581-8581/net.yuanjin I/test0: main ,id = 1
08-17 09:06:14.028 8581-8581/net.yuanjin I/test1: main ,id = 1
08-17 09:06:14.028 8581-8581/net.yuanjin I/test2: main ,id = 1
08-17 09:06:14.036 8581-8581/net.yuanjin I/test3: main ,id = 1

As you can see, when subscribeOn and observeOn are not used, all operations are performed in the main thread.

  • 2. Use subscribe On only
/**
 * Use subscribeOn only (Schedulers. newThread ())
 */
private void test4() {
    Log.i("test0",Thread.currentThread().getName().toString() + " ,id = "+Thread.currentThread().getId());
    Observable.create(new Observable.OnSubscribe<Integer>() {
        @Override
        public void call(Subscriber<? super Integer> subscriber) {
            Log.i("test1",Thread.currentThread().getName().toString() + " ,id = "+Thread.currentThread().getId());
            subscriber.onNext(R.drawable.picasso_drawable);
        }
    })
    .map(new Func1<Integer, Drawable>() {
        @Override
        public Drawable call(Integer integer) {
            Log.i("test2",Thread.currentThread().getName().toString() + " ,id = "+Thread.currentThread().getId());
            return getResources().getDrawable(integer);
        }
    })
    .subscribeOn(Schedulers.newThread())
    .subscribe(new Subscriber<Drawable>() {
        @Override
        public void onCompleted() {}

        @Override
        public void onError(Throwable e) {}

        @Override
        public void onNext(Drawable drawable) {
            Log.i("test3",Thread.currentThread().getName().toString() + " ,id = "+Thread.currentThread().getId());
        }
    });
}

Output results:

08-17 09:13:02.052 15056-15056/net.yuanjin I/test0: main ,id = 1
08-17 09:13:02.052 15056-15402/net.yuanjin I/test1: RxNewThreadScheduler-2 ,id = 272
08-17 09:13:02.052 15056-15402/net.yuanjin I/test2: RxNewThreadScheduler-2 ,id = 272
08-17 09:13:02.056 15056-15402/net.yuanjin I/test3: RxNewThreadScheduler-2 ,id = 272

As you can see, when subscribeOn(Schedulers.newThread()) is used, all of test1 - test3 is executed in the same new thread. So subscribeOn affects the threads of all events starting from the trigger event (test1) and subsequently (if the threads of subsequent events are not redefined)

  • 3. Use observeOn only
/**
 * Use only observeOn(Schedulers.newThread())
 */
private void test4() {
    Log.i("test0",Thread.currentThread().getName().toString() + " ,id = "+Thread.currentThread().getId());
    Observable.create(new Observable.OnSubscribe<Integer>() {
        @Override
        public void call(Subscriber<? super Integer> subscriber) {
            Log.i("test1",Thread.currentThread().getName().toString() + " ,id = "+Thread.currentThread().getId());
            subscriber.onNext(R.drawable.picasso_drawable);
        }
    })
    .map(new Func1<Integer, Drawable>() {
        @Override
        public Drawable call(Integer integer) {
            Log.i("test2",Thread.currentThread().getName().toString() + " ,id = "+Thread.currentThread().getId());
            return getResources().getDrawable(integer);
        }
    })
    .observeOn(Schedulers.newThread())//Note the location of observeOn, before test3
    .subscribe(new Subscriber<Drawable>() {
        @Override
        public void onCompleted() {}

        @Override
        public void onError(Throwable e) {}

        @Override
        public void onNext(Drawable drawable) {
            Log.i("test3",Thread.currentThread().getName().toString() + " ,id = "+Thread.currentThread().getId());
        }
    });
}

Output results:

08-17 09:21:24.032 23435-23435/net.yuanjin I/test0: main ,id = 1
08-17 09:21:24.036 23435-23435/net.yuanjin I/test1: main ,id = 1
08-17 09:21:24.036 23435-23435/net.yuanjin I/test2: main ,id = 1
08-17 09:21:24.044 23435-23772/net.yuanjin I/test3: RxNewThreadScheduler-1 ,id = 332

As you can see, in the code, observeOn precedes test3, which makes subsequent test3 execute on new threads, whereas prior test3 executes on main threads.

  • 4. Use only observeOn(Schedulers.newThread()). Note: Position changes compared with 3
/**
 * Use only observeOn(Schedulers.newThread())
 */
private void test4() {
    Log.i("test0",Thread.currentThread().getName().toString() + " ,id = "+Thread.currentThread().getId());
    Observable.create(new Observable.OnSubscribe<Integer>() {
        @Override
        public void call(Subscriber<? super Integer> subscriber) {
            Log.i("test1",Thread.currentThread().getName().toString() + " ,id = "+Thread.currentThread().getId());
            subscriber.onNext(R.drawable.picasso_drawable);
        }
    })
    .observeOn(Schedulers.newThread())//Note that observeOn is located before test2
    .map(new Func1<Integer, Drawable>() {
        @Override
        public Drawable call(Integer integer) {
            Log.i("test2",Thread.currentThread().getName().toString() + " ,id = "+Thread.currentThread().getId());
            return getResources().getDrawable(integer);
        }
    })
    .subscribe(new Subscriber<Drawable>() {
        @Override
        public void onCompleted() {}

        @Override
        public void onError(Throwable e) {}

        @Override
        public void onNext(Drawable drawable) {
            Log.i("test3",Thread.currentThread().getName().toString() + " ,id = "+Thread.currentThread().getId());
        }
    });
}

Results Output:

08-17 09:27:14.612 29242-29242/net.yuanjin I/test0: main ,id = 1
08-17 09:27:14.616 29242-29242/net.yuanjin I/test1: main ,id = 1
08-17 09:27:14.616 29242-29442/net.yuanjin I/test2: RxNewThreadScheduler-1 ,id = 362
08-17 09:27:14.620 29242-29442/net.yuanjin I/test3: RxNewThreadScheduler-1 ,id = 362

As you can see, in the code observeOn precedes test2, which causes subsequent test2, test3 to execute on new threads, while prior to that, it executes on main threads.

In summary, you can see that observeOn changes the threads of all operations after its location

  • 5. Use observeOn() and subscribeOn()
/**
 * Use observeOn() and subscribeOn()
 */
private void test4() {
    Log.i("test0",Thread.currentThread().getName().toString() + " ,id = "+Thread.currentThread().getId());
    Observable.create(new Observable.OnSubscribe<Integer>() {
        @Override
        public void call(Subscriber<? super Integer> subscriber) {
            Log.i("test1",Thread.currentThread().getName().toString() + " ,id = "+Thread.currentThread().getId());
            subscriber.onNext(R.drawable.picasso_drawable);
        }
    })
    .map(new Func1<Integer, Drawable>() {
        @Override
        public Drawable call(Integer integer) {
            Log.i("test2",Thread.currentThread().getName().toString() + " ,id = "+Thread.currentThread().getId());
            return getResources().getDrawable(integer);
        }
    })
    .subscribeOn(Schedulers.newThread())//Setting up new threads
    .observeOn(AndroidSchedulers.mainThread())//Set it as the main thread
    .subscribe(new Subscriber<Drawable>() {
        @Override
        public void onCompleted() {}

        @Override
        public void onError(Throwable e) {}

        @Override
        public void onNext(Drawable drawable) {
            Log.i("test3",Thread.currentThread().getName().toString() + " ,id = "+Thread.currentThread().getId());
        }
    });
}

Output results:

08-17 09:39:04.976 8056-8056/net.yuanjin I/test0: main ,id = 1
08-17 09:39:04.984 8056-9290/net.yuanjin I/test1: RxNewThreadScheduler-1 ,id = 406
08-17 09:39:04.984 8056-9290/net.yuanjin I/test2: RxNewThreadScheduler-1 ,id = 406
08-17 09:39:05.012 8056-8056/net.yuanjin I/test3: main ,id = 1

As you can see, subscribeOn changes the running threads of test1 and subsequent operations to new threads. Because observeOn was before test3, the running thread of test3 was changed to the main thread.

  • 6. Use observeOn() and subscribeOn()
/**
 * Use observeOn() and subscribeOn()
 */
private void test4() {
    Log.i("test0",Thread.currentThread().getName().toString() + " ,id = "+Thread.currentThread().getId());
    Observable.create(new Observable.OnSubscribe<Integer>() {
        @Override
        public void call(Subscriber<? super Integer> subscriber) {
            Log.i("test1",Thread.currentThread().getName().toString() + " ,id = "+Thread.currentThread().getId());
            subscriber.onNext(R.drawable.picasso_drawable);
        }
    })
    .observeOn(AndroidSchedulers.mainThread())//Set it to the main thread, before test2
    .map(new Func1<Integer, Drawable>() {
        @Override
        public Drawable call(Integer integer) {
            Log.i("test2",Thread.currentThread().getName().toString() + " ,id = "+Thread.currentThread().getId());
            return getResources().getDrawable(integer);
        }
    })
    .observeOn(Schedulers.newThread())//Set it to a new thread, before test3
    .subscribeOn(Schedulers.newThread())
    .subscribe(new Subscriber<Drawable>() {
        @Override
        public void onCompleted() {}

        @Override
        public void onError(Throwable e) {}

        @Override
        public void onNext(Drawable drawable) {
            Log.i("test3",Thread.currentThread().getName().toString() + " ,id = "+Thread.currentThread().getId());
        }
    });
}

Output results:

08-17 09:46:35.132 16555-16555/net.yuanjin I/test0: main ,id = 1
08-17 09:46:35.136 16555-16999/net.yuanjin I/test1: RxNewThreadScheduler-1 ,id = 491
08-17 09:46:35.180 16555-16555/net.yuanjin I/test2: main ,id = 1
08-17 09:46:35.184 16555-17000/net.yuanjin I/test3: RxNewThreadScheduler-2 ,id = 492

As you can see, subscribeOn changed test1 and subsequent threads to new threads. Because observeOn was used to change the thread to the main thread before test2, test2 runs on the main thread. Later, because subscribeOn was used to change the thread to a new thread before test3, test3 ran on the new thread.

So far, you can see
1. subscribeOn changes the threads of all operations from the trigger event (test1) and beyond, regardless of placement.
2. The observeOn changes the threads of all subsequent operations and can be used multiple times, depending on location.

Posted by phpfre@k* on Mon, 03 Jun 2019 20:17:03 -0700