【问题标题】:How to return a Rx Single transaction using Room Db?如何使用 Room Db 返回 Rx Single 交易?
【发布时间】:2019-04-01 20:47:13
【问题描述】:

假设有一个Dao 类有以下两个方法:

1)

delete(items: List<Item>): Completable

2)

 insert(items: List< Item >): Single<List<Long>>

如何将它们链接到 Dao 类中的 @transaction 方法中,从“删除方法”开始,然后返回“插入方法”结果?

我想要一个带有这样签名的方法:

@Transaction
fun deleteAndInsert(): Single<List<Long> > {
    ...
}

【问题讨论】:

    标签: android rx-java2 android-room


    【解决方案1】:

    我假设您的主要目标是将deleteAndInsert() 的返回类型设为Single

    您只需稍作修改即可实现这一目标

    • 首先使delete()insert() 函数同步。
    • 由于@Transaction 只能同步工作,我们需要创建另一个同时调用delete()insert() 的函数。另外,用@Transaction注释这个函数
    • 创建另一个新函数,该函数创建 Single 并调用上述函数。

    abstract class SampleDao{
        protected abstract fun delete()
        protected abstract fun insert(items: List<Item>) : List<Long>
    
        @Transaction
        protected open fun deleteAndInsertSync(items: List<Item>): List<Long>{
            delete()
            return insert(items)
        }
    
        fun deleteAndInsert(items:List<Item>): Single<List<Long>>{
            return Single.create {
                it.onSuccess(deleteAndInsertSync(items))
            }
        }
    }
    

    【讨论】:

      【解决方案2】:

      我认为这是不可能的。

      我曾经尝试过,但出现编译时错误:

      "用@Transaction注解的方法不能返回deferred/async 返回类型 io.reactivex.Single。由于事务是线程 限制和房间不能保证方法中的所有查询 实现都是在同一个线程上执行的,只有同步的 允许使用 @Transaction 实现的方法。如果交易是 启动并完成线程更改并等待数据库 如果附加线程尝试执行 询问。此限制可防止此类情况发生。”

      【讨论】:

        【解决方案3】:
        • 用@Transaction 注释的方法不能返回延迟/异步返回类型io.reactivex.Single。由于事务是线程受限的,Room 不能保证方法实现中的所有查询都在同一个线程上执行,因此只允许同步 @Transaction 实现的方法。如果启动事务并且完成并等待线程更改,则如果附加线程尝试执行查询,则可能发生数据库死锁。此限制可防止此类情况发生。
        • 当我将代码反编译为 java 时,我看到了。

          public interface CustomerDao {
          @Transaction
          @NotNull
          List deleteAndCreate(@NotNull List var1);
          
          @Query("DELETE FROM customer")
          @NotNull
          Completable deleteAll();
          
          @Insert
          @NotNull
          List insertAll(@NotNull List var1);
          
          @Metadata(
             mv = {1, 1, 15},
             bv = {1, 0, 3},
             k = 3
          )
          public static final class DefaultImpls {
             @Transaction
             @NotNull
             public static List deleteAndCreate(CustomerDao $this, @NotNull List 
               users) 
             {
                Intrinsics.checkParameterIsNotNull(users, "users");
                $this.deleteAll();
                return $this.insertAll(users);
             }
          }
          }
          

        【讨论】:

          【解决方案4】:

          获取新数据的 ID

          然后删除所有不在新数据中的项目

          @Query("DELETE FROM product WHERE id NOT IN(:idsNewItems)")
              @Override
              public abstract void deleteOldItems(List<String> idsNewItems)
          

          ;

          【讨论】:

            【解决方案5】:

            如果您的deleteinsert 方法标有注释,则它们正在事务中执行。所以,基本上你不需要用这个注解来标记你的deleteAndInsert 方法。所以,比:

            fun deleteAndInsert(items: List< Item >): Single<List<Long>> {
                return delete().andThan(insert(items))
            }
            

            【讨论】:

            • 我认为它们不会在同一个事务中执行。
            猜你喜欢
            • 1970-01-01
            • 2022-06-15
            • 1970-01-01
            • 1970-01-01
            • 2018-06-18
            • 2018-08-13
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多