You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

测试中使用Looper调度器时Observable.create未执行的问题排查

问题分析与解决方案:Observable.create代码块未执行(Looper调度器场景)

我来帮你分析下这个问题,你遇到的Observable.create里的代码块完全没执行的情况,大概率和Looper调度器的线程状态或者测试逻辑有关,咱们一步步来拆解:

首先先明确你的问题代码:
待测试代码:

public Observable<Void> prepare() {
    return Observable.<Void>create(subscriber -> {
        // 此处代码从未执行
        subscriber.onCompleted();
    }).subscribeOn(scheduler);
}

其中scheduler是继承自HandlerThread的Looper调度器,测试使用TestSubscriber。

核心原因排查

1. Looper调度器的线程未正确启动

subscribeOn(scheduler)会把Observable.create中的逻辑包装成任务,提交到调度器对应的线程消息队列中。但如果你的Looper调度器(也就是那个继承HandlerThread的类)没有调用start()方法启动线程,那么线程的Looper根本不会运行,消息队列里的任务永远不会被执行。

2. 测试代码未等待任务执行完成

在单元测试场景下,如果你的TestSubscriber没有等待Observable执行完成,测试方法可能在Looper线程的任务还没来得及执行时就已经结束了,看起来就像代码块没跑过一样。

针对性解决方案

方案一:确保Looper调度器的HandlerThread已启动

检查你的Looper调度器实现,必须调用start()来启动线程,并且初始化Handler时要拿到有效的Looper。示例实现如下:

public class LooperScheduler extends HandlerThread implements Scheduler {
    private Handler handler;

    public LooperScheduler(String threadName) {
        super(threadName);
        // 必须启动线程,否则Looper不会工作
        start();
        // 等待Looper初始化完成(HandlerThread的getLooper会阻塞直到Looper创建)
        handler = new Handler(getLooper());
    }

    @Override
    public Worker createWorker() {
        return new Worker() {
            @Override
            public Subscription schedule(Action0 action) {
                handler.post(() -> action.call());
                return Subscriptions.empty();
            }

            @Override
            public void unsubscribe() {
                handler.removeCallbacksAndMessages(null);
            }

            @Override
            public boolean isUnsubscribed() {
                return false;
            }
        };
    }
}

重点提醒:一定要调用start(),这是很多人容易忽略的点!

方案二:完善测试代码,等待Observable执行完成

修改你的测试代码,添加等待终端事件的逻辑,确保测试不会提前结束:

@Test
public void prepare() throws Exception {
    TestSubscriber<Void> testSubscriber = new TestSubscriber<>();
    // 订阅Observable
    prepare().subscribe(testSubscriber);
    
    // 等待Observable完成,设置合理的超时时间
    testSubscriber.awaitTerminalEvent(5, TimeUnit.SECONDS);
    
    // 验证结果:确认onCompleted被调用,且无错误
    testSubscriber.assertCompleted();
    testSubscriber.assertNoErrors();
}

如果没有awaitTerminalEvent这一步,测试方法会直接走完,而Looper线程的任务还在排队,自然看不到代码块执行的痕迹。

方案三:验证调度器实例有效性

最后可以在prepare()方法里加个简单的日志,确认scheduler不是null,并且对应的线程是活跃状态:

public Observable<Void> prepare() {
    // 打印调度器线程状态,排查问题
    Log.d("SchedulerCheck", "Scheduler thread alive: " + scheduler.isAlive());
    return Observable.<Void>create(subscriber -> {
        // 此处代码从未执行
        subscriber.onCompleted();
    }).subscribeOn(scheduler);
}

按照这几个步骤排查和修复,应该就能解决代码块未执行的问题了。

内容的提问来源于stack exchange,提问作者Itay k

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 11:12:02