正确使用调度程序

时间:2018-11-06 14:29:33

标签: android rx-java

我正在尝试从文件系统读取文件,更新房间数据库并最终更新UI。这似乎是一个特别简单的任务,但是我在正确使用Android和RxJava Scheduler方面遇到了困难。

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_welcome);

    this.loadingTextView = this.findViewById(R.id.tvLoading);

    this.subscription = Observable.just(0)
            .subscribeOn(Schedulers.io())
            .flatMap(ignore -> engine.checkEngineRequirements())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(ignore-> Log.e("glog", "Received on thread " + Thread.currentThread().getName()),
                    throwable -> Log.e("glog", "[WelcomeActivity.onCreate()]:" + throwable.getMessage()),
                    () -> {
                        this.loadingTextView.setText("Loaded");
                        Log.d("glog", "[WelcomeActivity] Launching new activity");
                        Intent intent = new Intent(this, PlayGameActivity.class);
                        this.startActivity(intent);
                    }
            );
}   

在checkEngineRequirements中,我正在从文件加载文件并填充房间数据库:

private Observable<Long> checkEngineRequirements() {
    return new OfflineDataLoad().load(this.context)                
            .observeOn(Schedulers.io())
            .flatMap(data -> this.dataRepository.addData(data));
}

public Observable<String> load(Context context) {
    return Observable.create(emitter -> {
        try {
            BufferedReader bufferedReader = new BufferedReader(
                    new InputStreamReader(
                            context.getAssets().open(DB_FILE_NAME), "UTF-8"));
            (...)
            while (lineAvailabe) {
                emitter.onNext(line)
            }
            emitter.onComplete();
        }
        catch (Exception e) {
            emitter.onError(e);
        }
    });
}

我的数据源(存储库)实现如下:

@Override
public Observable<Long> addData(Data newDataItem) {
    return Observable.fromCallable(() -> this.dataDao.insertData(newDataItem));
}

问题在于永远不会调用onComplete事件。知道我在做什么错吗?

1 个答案:

答案 0 :(得分:1)

基于评论:

对序列进行故障排除的一般方法是使用doOnXXXX运算符并记录各种事件。

在这种情况下,所描述的流程并不意味着任何无限序列(因为这在Room查询中非常常见),并且没有做任何特别复杂的事情。因此,剩下的就是存储的subscription变量,以及当从主线程上的onCreate内部启动时,代码的主要部分在后台运行并且最终可能会返回的事实。再次进入主线程。

这给UI提供了充足的时间来销毁UI,并销毁了上述subscription。当然,可以肯定的是,将doOnDispose()应用于日志记录时应尽可能接近最终用户,并且应该已经证明确实是这种情况:

this.subscription = Observable.just(0)
        .subscribeOn(Schedulers.io())
        .flatMap(ignore -> engine.checkEngineRequirements())
        .observeOn(AndroidSchedulers.mainThread())
        // v---------------------------------v-----------------------------------v----
        .doOnDispose(() -> Log.e("glog", "[WelcomeActivity.onCreate()]: Disposed"))
        // ^---------------------------------^-----------------------------------^--
        .subscribe(ignore-> Log.e("glog", "Received on thread " 
                     + Thread.currentThread().getName()),
                throwable -> Log.e("glog", "[WelcomeActivity.onCreate()]:" 
                     + throwable.getMessage()),
                () -> {
                    this.loadingTextView.setText("Loaded");
                    Log.d("glog", "[WelcomeActivity] Launching new activity");
                    Intent intent = new Intent(this, PlayGameActivity.class);
                    this.startActivity(intent);
                }
        );