在concat map

时间:2016-07-06 15:57:12

标签: java android multithreading transactions rx-java

你好RxJava大师,

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

  1. 我在线程上启动一个事务
  2. 调用Web服务并将一些内容保存在数据库中
  3. concat map另一个可观察的函数
  4. 尝试在数据库上写其他东西--->陷入僵局
  5. 这是我的代码:

    //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
    }
    

    为什么所有突然的RxJava都在改变线程?即使我指定我希望他在我自己的调度程序上观察。我通过在saveSubItem之前添加另一个observeOn做了一个脏修复,但这可能不是正确的解决方案。

    我知道当您通过改造调用Web服务时,响应将转发到新线程(这就是为什么我创建自己的调度程序以回到我开始执行sql事务的线程中的原因)。但是,我真的不明白RxJava是如何管理线程的。

    非常感谢你的帮助。

2 个答案:

答案 0 :(得分:1)

副作用运算符(和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();

答案 1 :(得分:-1)

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

示例:您可以执行多次休息调用,将其保存到数据库,并在doOnNext(...)内部通知视图/演示者/控制器。您可以在保存到数据库之前或/和保存到数据库之后执行此操作。 我建议你是&#34; flatMapping&#34;代码。

因此saveItems方法看起来像这样(如果myStore.saveSubItems返回结果):

public Observable<Node> saveSubItems(Item item) {
return Observable.from(item.getSubItems())
        .flatMap(subItem -> myStore.saveSubItems(subItem))
}

使用&#34; flatMapping&#34;保证操作在与前一个序列相同的线程上运行,并且序列继续,然后flaMap函数结束。