为什么RxJava的“订阅”方法被多次调用?

时间:2018-07-17 07:14:47

标签: android kotlin rx-java rx-java2

我正在使用RxJava开发一个Android应用程序。 例如,我想从本地数据库中获取一些用户数据。 但是,如果本地数据库没有用户,我应该使用REST API来吸引用户。

class Presenter {
    val mDisposable = CompositeDisposable()

    override fun getUsersFromLocal() {
        Log.d("TAG", "This is called just one")
        mDisposable.add(localDatabase.userDao().getUsers()
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe { // This "subscribe" is the problem. Here is called multiple......
                Log.d("TAG", "This subscribe is called multiple, It called more than 10 times")
                if (it.isEmpty()) {
                    secondCall()
                } else {
                    view.onUsersLoaded(it)
                }
            })
    }

    override fun getUsersFromRemote() {
        mDisposable.add(restApi.getUsers()
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe {
                saveLocal(it) // If I remove just this line, subscribe is called once. (works fine)
                view.onUsersLoaded(it)
            })
    }
}

我正在使用嵌套的(?)RxJava。 我不知道为什么firstCall的订阅方法称为多... 如果删除“ secondCall()”方法和逻辑,则“订阅”仅调用一次。


我找到了一个线索。 “ saveLocal”方法正在后台线程中运行。

    private fun saveLocal(users: List<User>) {
        users.forEach {
            appExecutors.diskIo.execute {
                localDatabase.userDao().saveUser(it)
            }
        }
    }

我将原始代码的上限更改为以下。

    private fun saveLocal(users: List<User>) {
        appExecutors.diskIo.execute {
            localDatabase.userDao().saveUsers(users)
        }
    }

更改后,“订阅”仅被调用两次。 是的,它仍然有问题。 但是在此之前,“订阅”被多次调用。 (我认为它与“用户”大小一样多。)


我也添加了“ UserDao类”和“ RestApi类”代码。

import android.arch.persistence.room.*
import io.reactivex.Flowable
import io.reactivex.Single

@Dao
interface UserDao {

    @Query("SELECT * FROM user ORDER BY id DESC")
    fun getUsers(): Flowable<List<User>>

}

这是“ RestApiService类”。

import io.reactivex.Observable

interface RestApiService {
    @Headers(API_HEADER_AUTHORIZATION, API_HEADER_ACCEPT)
    @GET("/users")
    fun getUsers(): Observable<UserList> // UserList class has a list of the user
}

2 个答案:

答案 0 :(得分:0)

对于您的案例,您需要使用“也许”而不是“可流动”。

使用Flowable,如果再次添加新数据或更新以前插入的对象,则Flowable对象将自动发出并再次调用subscription方法:

此更改可能会修复您的代码:

@Dao
interface UserDao {

    @Query("SELECT * FROM user ORDER BY id DESC")
    fun getUsers(): Maybe<List<User>>

}

有关Flowable,Single和也许的更多信息,请参见下面的文章” Room implementation with RxJava

答案 1 :(得分:-1)

您应该使用switchIfEmpty运算符,而不要在预订中使用if语句。基本上,您进行两个订阅