简体   繁体   English

即使在另一个线程上调用了subscribeOn(),Observable也会在主线程上运行

[英]Observable runs on main thread even though subscribeOn() is called on another thread

I got a weird issue in one of my activities. 我在其中一项活动中遇到了一个奇怪的问题。 When coming back from taking a picture / video, in my onActivityResult I am showing a dialog that lets the user name the camera. 当从拍摄照片/视频回来时,在我的onActivityResult我正在显示一个对话框,让用户为相机命名。 Once the user presses OK, I send onNext() to a subject with the requested file name that copies the file (and shows progress dialog). 一旦用户按下OK,我onNext()发送给具有复制文件的请求文件名的主题​​(并显示进度对话框)。

For some reason the map() function that does the copy is always called on the main thread, even though I call subscribeOn(Schedulers.io()) . 由于某种原因,即使我调用subscribeOn(Schedulers.io()) ,也总是在主线程上调用执行复制的map()函数。

@Override
protected void onActivityResult(final int requestCode, int resultCode, Intent intent) {
    ...

    final PublishSubject<String> subject = PublishSubject.create();`

    mSubscription = subject
            .subscribeOn(Schedulers.io())
            .map(new Func1<String, String>() {
                @Override
                public String call(String fileName) {
                    Log.I.d(TAG,"map");
                    return doSomeIOHeavyFuncition();
                }
            })
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Action1<String>() {
                @Override
                public void call(final String fullPath) {
                    Log.d(TAG,"onNext");
                    doSomethingOnUI(fullPath);

                    subject.onCompleted();
                }
            }, new Action1<Throwable>() {
                @Override
                public void call(Throwable throwable) {
                    ...
                }
            }, new Action0() {
                @Override
                public void call() {
                    ...
                }
            });

    final AlertDialog dialog = new AlertDialog.Builder
    ....
    .create()
            .show();

    dialog.getButton(DialogInterface.BUTTON_POSITIVE)
            .setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    String someString = getStringFromDialog(dialog);

                    dialog.dismiss();
                    InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                    imm.hideSoftInputFromWindow(input.getWindowToken(), 0);

                    showProgressDialog();
                    subject.onNext(someString);
                }
            });
}

Changing the subscribeOn(Schedulers.io()) call to observeOn(Schedulers.io()) solved the issue. subscribeOn(Schedulers.io())调用更改为observeOn(Schedulers.io())解决了这个问题。 Still I would like to know why it didn't work... 我仍然想知道为什么它不起作用......

subscribeOn and observeOn is the mostly confused operators there are. subscribeOnobserveOnobserveOn被混淆的运算符。 The former makes sure that subscription side effects happen on the specified scheduler (thread), but that doesn't mean that values will pop up on that thread as well. 前者确保订阅副作用发生在指定的调度程序(线程)上,但这并不意味着值也将弹出该线程。

For example, if your Observer opens a network connection when one subscribes to it, you don't want that to run on the main thread, therefore, you need subscribeOn to specify where that subscription and thus the network connection will be created. 例如,如果您的Observer在订阅它时打开网络连接,您不希望它在主线程上运行,因此,您需要subscribeOn来指定该订阅的位置以及因此将创建网络连接。

When data finally arrives, the emitting thread can be anything, one of the schedulers or a background plain old thread. 当数据最终到达时,发送线程可以是任何东西,调度程序之一或后台普通旧线程。 Since we don't know or don't like that thread, we want to move the observation of the data to another thread. 由于我们不知道或不喜欢该线程,我们希望将数据的观察移动到另一个线程。 This is what observeOn does: makes sure operators after it will execute their onNext logic on the specified scheduler. 这就是observeOn的作用:确保后面的运算符将在指定的调度程序上执行onNext逻辑。 Android devs use it already to move the observation of values back to the main thread. Android开发人员已经使用它将值的观察结果移回主线程。

What's rarely explained though is what happens when you want some extra computation off the main thread before the final result lands on the main thread again: use multiple observeOn operators: 但是很少解释的是当你想要在最终结果再次落在主线程上之前在主线程上进行一些额外的计算时会发生什么:使用多个observeOn运算符:

source
.observeOn(Schedulers.computation())
.map(v -> heavyCalculation(v))
.observeOn(Schedulers.io())
.doOnNext(v -> { saveToDB(v); })
.observeOn(AndroidSchedulers.mainThread())
...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 即使指定了subscribeOn,代码仍在主线程上运行 - Code running on main thread even with subscribeOn specified 主线程中的SubscribeOn和observeOn - SubscribeOn and observeOn in the main thread 在与Observable相同的线程中运行subscriptionOn操作 - Running subscribeOn action in the same thread as Observable 即使有while循环,主线程也会死掉 - main thread is getting dead even though while loop is there 调用run方法后,主线程是否被另一个线程中断? - Main thread being interrupted by another thread after run method is called? 如果一个方法属于另一个扩展Thread的类但从主线程调用,则该方法是由主线程还是子线程执行? (JAVA) - If a method belongs to another class that extends Thread but is called from the main thread, will it be executed by main or a child thread? (Java) 即使我使用异步线程(主UI),主线程也进行了大量工作 - Main thread doing too much work even though I use an async thread (laggy UI) 主线程如何在此线程之前运行? - How main thread runs before this thread? 即使我正在处理另一个,UI线程也会卡住 - UI Thread gets stuck even though I'm working on another Android UI挂在JDBC连接上-即使连接在另一个线程上 - Android UI Hangs on JDBC Connection - Even though Connection is on another Thread
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM