Why onNext() is updating textview, though observeOn(Schedulars.io()) on a different thread?

℡╲_俬逩灬. 提交于 2021-02-11 04:31:19

问题


Observable.range(11,10).subscribeOn(Schedulers.io())
            .observeOn(Schedulers.io())
            .subscribe(new Observer<Integer>() {
                @Override
                public void onSubscribe(@NonNull Disposable d) {

                }

                @Override
                public void onNext(@NonNull Integer integer) {
                    textView.setText(String.valueOf(integer));
                    Log.d(TAG, "onNext: "+Thread.currentThread().getName());
                }

                @Override
                public void onError(@NonNull Throwable e) {

                }

                @Override
                public void onComplete() {

                }
            });

onNext() supposed to run on separate thread, but how is it updating textview, which is on main thread?


回答1:


It seems that at the very beginning of the lifetime of a view, there is a very short timespan where you are able to change the view off the main thread.

As you started a thread off the main thread, directly in onCreate(), and this thread almost instantly returns a result (as there is no real work to do) you will not get a CalledFromWrongThreadException when you adjust the view.

If you put a short delay (maybe it is different on your machine) - for me, 50ms was enough - before the work in the thread / Observable starts, you will see the expected CalledFromWrongThreadException.

Observable.just("first")
  .subscribeOn(Schedulers.newThread())
  .delay(50, TimeUnit.MILLISECONDS)
  .observeOn(Schedulers.newThread())
  .subscribe(item -> {
    textView.setText(item); // after the delay you will get a CalledFromWrongThreadException
  });

And this is not related to RxJava. Creating a Thread which updates the view immediately shows the same behavior:

new Thread(new Runnable() {
  @Override
  public void run() {
    textView.setText("foo"); // no CalledFromWrongThreadException
  }
}).start();

Looks like this issue goes back to ViewRootImpl checkThread() which did not get called in this case. For further understanding follow the links below.

Despite, any change to a view should happen from the main thread. The scenario you have shown seems like a "lucky" side-effect.

Documentation

  • Android UI Not Crashing When Modifying View off UI Thread
  • Why is there no CalledFromWrongThreadException when a new thread operates UI immediately?



回答2:


If you are using Data Binding Library, it allows to update the UI off the main thread.

You can change your data model in a background thread as long as it isn't a collection. Data binding localizes each variable / field during evaluation to avoid any concurrency issues.




回答3:


observeOn is an async operation and after its processed , the result to pushed to onNext whixh is intended to run on the UI thread. They are changing the threading for us.Thats an advantage isnt? Its the feature of RxJava



来源:https://stackoverflow.com/questions/65502555/why-onnext-is-updating-textview-though-observeonschedulars-io-on-a-differ

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!