当前位置: 首页 > 面试题库 >

即使在另一个线程上调用subscribeOn(),也可以在主线程上运行

麻宾白
2023-03-14
问题内容

我的一项活动遇到了一个奇怪的问题。从拍照/录像回来时,onActivityResult我正在显示一个对话框,允许用户命名相机。用户按下“确定”后,我将onNext()使用所请求的文件名发送给主题,该主题将复制文件(并显示进度对话框)。

由于某种原因map(),即使我调用,总是在主线程上调用执行复制的函数subscribeOn(Schedulers.io())

@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);
                }
            });
}

更改subscribeOn(Schedulers.io())呼叫以observeOn(Schedulers.io())解决问题。我还是想知道为什么它不起作用…


问题答案:

subscribeOn并且observeOn是那里最混乱的运营商。前者确保订阅副作用在指定的调度程序(线程)上发生,但这并不意味着值也将在该线程上弹出。

例如,如果您的观察者在订阅时打开了一个网络连接,则您不希望该链接在主线程上运行,因此,您需要subscriptionOn来指定该订阅的位置,从而创建网络连接。

当数据最终到达时,发出线程可以是任何东西,调度程序之一或后台普通旧线程。由于我们不知道或不喜欢该线程,因此我们希望将对数据的观察移到另一个线程。这是observeOn的作用:确保操作符之后的操作符将在指定的调度程序上执行其onNext逻辑。Android开发人员已经使用它来将对值的观察移回主线程。

但是很少解释的是,当您希望在最终结果再次落入主线程之前又需要在主线程上进行一些额外的计算时会发生什么:使用多个observeOn运算符:

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


 类似资料:
  • 我有以下代码: 第三方DK。doSomeAction回调在主线程上发布,因此发射器也将在主线程上发出,而不是在订阅线程上发出(如果我在flatMap中进一步进行一些网络交互,链将失败)。 如果我在第一个之后添加,它会切换到正确的线程,但是有没有办法在正确的线程上发出?我不能修改行为。

  • 在一个android服务中,我创建了用于执行一些后台任务的线程。 我遇到一个情况,线程需要在主线程的消息队列上发布特定任务,例如。 有没有方法获取主线程的并从我的另一个线程向它发布/?

  • 例如: 假设有一个按钮启动异步请求,该请求返回并触发主线程上运行的runnable/callback。会发生什么?runnable被添加到MessageQueue中,并在“时间”到时运行。但是什么时候是“时间”呢?如果在异步请求将runnable发布到MainThread之前,我按下另一个按钮,在MainThread上执行一些半长的阻塞任务呢?它会等到我的阻塞按钮上的逻辑完成吗?会打断它吗?它是否

  • 问题内容: 这是一个普遍的Java问题,而不是Android的第一个问题! 我想从二级线程的上下文中了解如何在主线程上运行代码。例如: 这类事情-我意识到我的示例有点差,因为在Java中,您不需要进入主线程即可打印出某些内容,并且Swing也具有事件队列- 但在一般情况下,您可能需要在后台线程的上下文中,在主线程上运行Runnable。 编辑:为了进行比较-这是我在Objective-C中的做法:

  • 问题内容: 因此,正如标题所述:将可运行对象从另一个线程发布到主线程时,实际上会发生什么? 我已经看到很多问题,询问您如何执行以及其基本原理。但是,当您将可运行对象放在MessageQueue上时,我很难找到确切的解释。当然,它在轮到Runnable时运行。但是什么时候呢? 因此,例如: 假设有一个按钮启动ASync请求,并且该请求返回并触发在MainThread上运行的可运行/回调。怎么了?可运

  • 问题内容: 我一直在弄乱Java中的线程来处理它们(这似乎是最好的方法),现在了解了sync,wait()和notify()的情况。 我很好奇是否有一种方法可以同时对两个资源进行wait()。我认为以下内容并不能完全满足我的想法( 编辑 : 请注意,此示例中省略了通常的while循环,仅专注于释放两个资源 ): 在这种(非常人为)情况下,将保留token2直到返回token1,然后将保留token