android - 在链订阅的线程上发出值
问题描述
问题
尝试在观察者中使用广播接收器时遇到问题。
BroadcastReceiver 发出的项目在主线程上发出,而不是在传递的线程上发出subscribeOn
。
代码 - 实际场景
例如,给定下面的代码,它与此链接中的 RxBroadcastReceiver 类几乎相同:
public static final class RxBroadcastReceiver implements ObservableOnSubscribe<String> {
public static Observable<String> create(Context context, IntentFilter intentFilter) {
return Observable.create(new RxBroadcastReceiver(context, intentFilter));
}
private final Context context;
private final IntentFilter intentFilter;
private RxBroadcastReceiver(Context context, IntentFilter intentFilter) {
this.context = context;
this.intentFilter = intentFilter;
}
@Override
public void subscribe(final ObservableEmitter<String> emitter) throws Exception {
final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String threadName = Thread.currentThread().getName();
emitter.onNext(threadName);
}
};
context.registerReceiver(broadcastReceiver, intentFilter);
emitter.setDisposable(Disposables.fromRunnable(new Runnable() {
@Override
public void run() {
context.unregisterReceiver(broadcastReceiver);
}
}));
}
}
运行以下代码时:
RxBroadcastReceiver.create(context, filter)
.subscribeOn(Schedulers.io())
.subscribe(new Consumer<String>() {
@Override
public void accept(final String executedThread) throws Exception {
String acceptedThread = Thread.currentThread().getName();
System.out.println("executedThread: " + executedThread);
System.out.println("acceptedThread: " + acceptedThread);
}
});
输出显示执行的线程是主线程,而不是来自 Schedulers.io 的线程:
executedThread: main
acceptedThread: main
代码 - 预期结果
而如果使用下面的代码:
public static final class RxJavaBroadcaster implements ObservableOnSubscribe<String> {
public static Observable<String> create() {
return Observable.create(new RxJavaBroadcaster());
}
@Override
public void subscribe(final ObservableEmitter<String> emitter) throws Exception {
String threadName = Thread.currentThread().getName();
emitter.onNext(threadName);
}
}
运行以下代码时:
RxJavaBroadcaster.create()
.subscribeOn(Schedulers.io())
.subscribe(new Consumer<String>() {
@Override
public void accept(final String executedThread) throws Exception {
String acceptedThread = Thread.currentThread().getName();
System.out.println("executedThread: " + executedThread);
System.out.println("acceptedThread: " + acceptedThread);
}
});
正如预期的那样,输出不在主线程中:
executedThread: RxCachedThreadScheduler-1
acceptedThread: RxCachedThreadScheduler-1
研究
我认为项目在主线程上发出的原因是因为BroadcastReceiver.onReceive总是在其进程的主线程中调用。
鉴于上述正确,我能想到的另一种解决方案是注册 BroadcastReceiver 并使用此方法传递自定义 Handler 。
然后我的问题是:
- 如何从 RxBroadcastReceiver 中检索
Scheduler
传递的正确信息?subscribeOn
- 如何创建绑定到该特定调度程序的处理程序?
有没有人看到不同的选择?
我的问题与这个问题中描述的完全一样,事实上我已经在使用那里提出的解决方案(调用第二个 subscribeOn),但我更喜欢不同的选择。
解决方案
如果我理解正确,您希望在特定调度程序上发出并在主线程上接受。我认为您的解决方案将使用 RxAndroid https://github.com/ReactiveX/RxAndroid
将代码从预期结果更改为使用observeOn(AndroidSchedulers.mainThread())
RxJavaBroadcaster.create()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<String>() {
@Override
public void accept(final String executedThread) throws Exception {
String acceptedThread = Thread.currentThread().getName();
System.out.println("executedThread: " + executedThread);
System.out.println("acceptedThread: " + acceptedThread);
}
});
推荐阅读
- javascript - 如何在反应中单击后退按钮时维护先前表单的表单值
- jquery - 通过仅单击复选框而不是其他任何位置并在 jquery DataTable 中创建全选复选框来选择行
- android - 使用后退按钮离开活动后,待定意图仍然存在
- c# - 如何将控制台输出从另一个类的方法打印到 Winform 列表框?
- ms-access - MS Access 未在链接的 Sharepoint 列表中显示超链接(图像)
- pine-script - 水平线松脚本带有标签标题
- reactjs - 如何解决这个错误 --> SDK 初始化时出错!DOMException:无法在“WorkerGlobalScope”上执行“importScripts”
- laravel - cURL 错误 60:Laragon 和 Laravel 广播的 SSL 证书问题
- java - 使用 http2 协议的带有 REST API 的 Spring Boot 客户端应用程序
- python - 烧瓶 url_for 不播放视频