【问题标题】:Android Room with RxJava handle empty query result使用 RxJava 处理空查询结果的 Android Room
【发布时间】:2017-10-28 04:02:00
【问题描述】:

尝试使用 RxJava 适配器测试新的 Android Room 库。如果我的查询从数据库返回 0 个对象,我想处理结果:

所以这里是DAO方法:

@Query("SELECT * FROM auth_info")
fun getAuthInfo(): Flowable<AuthResponse>

以及我的处理方式:

        database.authDao().getAuthInfo()
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .switchIfEmpty { Log.d(TAG, "IS EMPTY") }
            .firstOrError()
            .subscribe(
                    { authResponse -> Log.d(TAG, authResponse.token) },
                    { error -> Log.d(TAG, error.message) })

我的数据库是空的,所以我希望 .switchIfEmty() 能够工作,但没有任何处理方法被触发。 .subscribe() 和 .switchIfEmpty() 都不是

【问题讨论】:

    标签: android kotlin rx-java2 android-room


    【解决方案1】:

    Db Flowables 是可观察的(因此如果数据库发生更改,它们会继续调度),因此它永远不会完成。您可以尝试返回List&lt;AuthResponse&gt;。我们考虑过向后移植一个可选选项,但决定不这样做,至少现在是这样。相反,我们可能会在不同的已知库中添加对 Optional 的支持。

    【讨论】:

    • 您应该考虑使用此功能的替代行为。当请求的结果为空时,我想获取 Flowable.empty()。
    • 房间查询是否返回一个大小为 0 的非空空列表?
    • @Query("SELECT COUNT (*) FROM User") Flowable getCount();如果没有用户,为什么不返回 0?我想跟踪用户数量..
    • 我们一直在使用 List 解决方案,但它仍然是一个 hack。 Room 找到更好的方法了吗?
    【解决方案2】:

    在 1.0.0-alpha5 版本中,room 添加了对 DAO 的 MaybeSingle 的支持,所以现在你可以编写类似的东西

    @Query("SELECT * FROM auth_info")
    fun getAuthInfo(): Maybe<AuthResponse>
    

    您可以阅读更多关于它的信息here

    【讨论】:

      【解决方案3】:

      switchIfEmptyPublisher&lt;AuthResponse&gt; 作为参数。通过 SAM 转换,您给定的匿名函数将转换为此类。但是,它不符合 Publisher 的预期行为,因此无法按预期工作。

      用正确的实现替换它,如Flowable.empty().doOnSubscribe { Log.d(TAG, "IS EMPTY") },它应该可以工作。

      【讨论】:

        【解决方案4】:

        您可以使用一些包装器来获取结果。例如:

        public Single<QueryResult<Transaction>> getTransaction(long id) {
                    return createSingle(() -> database.getTransactionDao().getTransaction(id))
                            .map(QueryResult::new);
        }
        
            public class QueryResult<D> {
                    public D data;
                    public QueryResult() {}
        
                    public QueryResult(D data) {
                        this.data = data;
                    }
        
                    public boolean isEmpty(){
                        return data != null;
                    }
         }
        
        protected <T> Single<T> createSingle(final Callable<T> func) {
                    return Single.create(emitter -> {
                        try {
                            T result = func.call();
                            emitter.onSuccess(result);
        
                        } catch (Exception ex) {
                            Log.e("TAG", "Error of operation with db");
                        }
                    });
        }
        

        在这种情况下,像“Single”一样使用它,无论如何你都会得到结果。使用:

        dbStorage.getTransaction(selectedCoin.getId())
                            .subscribeOn(Schedulers.io())
                            .observeOn(AndroidSchedulers.mainThread())
                            .subscribe(r -> {
                                 if(!r.isEmpty()){
                                   // we have some data from DB
                                 } else {
                               }
                            })
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-05-25
          • 1970-01-01
          • 2018-10-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多