concat映射后RxJava更改线程

concat映射后RxJava更改线程,java,android,multithreading,transactions,rx-java,Java,Android,Multithreading,Transactions,Rx Java,你好,RxJava大师 在我当前的Android项目中,我在使用RxJava和SQLite时遇到了一些死锁问题。我的问题是: 我在线程上启动一个事务 调用web服务并在数据库中保存一些内容 concat映射另一个可观测函数 尝试在数据库中写入其他内容--->出现死锁 这是我的密码: //define a scheduler for managing transaction in the same thread private Scheduler mScheduler = Schedulers.f

你好,RxJava大师

在我当前的Android项目中,我在使用RxJava和SQLite时遇到了一些死锁问题。我的问题是:

  • 我在线程上启动一个事务
  • 调用web服务并在数据库中保存一些内容
  • concat映射另一个可观测函数
  • 尝试在数据库中写入其他内容--->出现死锁
  • 这是我的密码:

    //define a scheduler for managing transaction in the same thread
    private Scheduler mScheduler = Schedulers.from(Executors.newSingleThreadExecutor());
    
    
    Observable.just(null)
                /* Go to known thread to open db transaction */
                .observeOn(mScheduler)
                .doOnNext(o -> myStore.startTransaction())
                /* Do some treatments that change thread */
                .someWebServiceCallWithRetrofit()
                /* Return to known thread to save items in db */
                .observeOn(mScheduler)
                .flatMap(items -> saveItems(items))
                .subscribe();
    
    public Observable<Node> saveItems(List<Item> items) {
        Observable.from(items)
                .doOnNext(item -> myStore.saveItem(item)) //write into the database OK
                .concatMap(tab -> saveSubItems(item));
    }
    
    public Observable<Node> saveSubItems(Item item) {
        return Observable.from(item.getSubItems())
                .doOnNext(subItem -> myStore.saveSubItems(subItem)) //DEADLOCK thread is different
    }
    
    //定义一个调度程序,用于管理同一线程中的事务
    私有调度程序mScheduler=Schedulers.from(Executors.newSingleThreadExecutor());
    可观察。仅(空)
    /*转到已知线程以打开db事务*/
    .observeOn(mScheduler)
    .doOnNext(o->myStore.startTransaction())
    /*做一些改变线程的处理*/
    .SomeWebServiceCallWithReformation()
    /*返回到已知线程以在数据库中保存项目*/
    .observeOn(mScheduler)
    .flatMap(项目->保存项目(项目))
    .subscribe();
    公共可观察保存项(列表项){
    可观察。来自(项目)
    .doOnNext(item->myStore.saveItem(item))//写入数据库确定
    .concatMap(选项卡->保存子项(项));
    }
    公共可观察保存子项(项){
    返回可观察的.from(item.getSubItems())
    .doOnNext(子项->myStore.saveSubItems(子项))//死锁线程不同
    }
    
    为什么RxJava突然改变了线程?即使我指定了,我也希望他在我自己的日程表上观察。我在saveSubItem之前添加了另一个observeOn,这是一个糟糕的修复,但这可能不是正确的解决方案

    我知道,当您通过改造调用web服务时,响应会转发到一个新线程(这就是为什么我创建了自己的调度程序以返回到启动sql事务的线程中)。但是,我真的不明白RxJava是如何管理线程的


    非常感谢您的帮助。

    据我所知,doOnNext方法是在不同的线程中调用的,与前面的代码不同,因为它是从序列的其余部分异步运行的。

    示例:您可以执行多个rest调用,将其保存到数据库,并在
    doOnNext(…)
    中通知视图/演示者/控制器程序。您可以在保存到数据库之前或/或保存到数据库之后执行此操作。 我建议您使用“flatMapping”代码

    因此,
    saveItems
    方法如下所示(如果
    myStore.saveSubItems
    返回一个结果):

    公共可观察保存子项(项){
    返回可观察的.from(item.getSubItems())
    .flatMap(子项->myStore.saveSubItems(子项))
    }
    
    使用“flatMapping”可以保证操作在与前一个序列相同的线程上运行,并且序列继续,然后
    flaMap
    函数结束。

    副作用操作符(正如
    flatMap
    一样)在任何线程调用它时同步执行。试试像这样的东西

    Observable.just(null)            
              .doOnNext(o -> myStore.startTransaction())
              .subscribeOn(mScheduler)      // Go to known thread to open db transaction 
                /* Do some treatments that change thread */
              .someWebServiceCallWithRetrofit()                      
              .flatMap(items -> saveItems(items))
              .subscribeOn(mScheduler) // Return to known thread to save items in db
              .observeOn(mScheduler) // Irrelevant since we don't observe anything
              .subscribe();
    
    Observable.just(null)            
              .doOnNext(o -> myStore.startTransaction())
              .subscribeOn(mScheduler)      // Go to known thread to open db transaction 
                /* Do some treatments that change thread */
              .someWebServiceCallWithRetrofit()                      
              .flatMap(items -> saveItems(items))
              .subscribeOn(mScheduler) // Return to known thread to save items in db
              .observeOn(mScheduler) // Irrelevant since we don't observe anything
              .subscribe();