Search code examples
androidmvvmretrofitrx-javaandroid-mvvm

request in another request called several times with rxJava and retrofit


I'm using MVVM and rxJava and retrofit to send my request. I have a bottom navigation view which has 5 fragments and in one of them, I have to send a request and after it, the response is delivered, I have to send another request to my server. this is my ViewModel class :

class MyViewModel: ViewModel() {

val compositeDisposable = CompositeDisposable()
val myFirstReqLiveData = MutableLiveData<myFirstReqModel>()
val mySecondReqLiveData = MutableLiveData<mySecondReqModel>()

    fun getFirstReq(token:String){

    val firstReqDisposable = RetrofitClientInstance.getRetrofitInterface()
        .getFirstReq(token)
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread()).singleElement()
        .subscribe({
                it-> myFirstReqLiveData.value = it
        },{
            errorFirstReqLiveData.value = it
        },{

        })
    compositeDisposable.add(firstReqDisposable)

}

    fun getSecondReq(token:String){

    val secondReqDisposable = RetrofitClientInstance.getRetrofitInterface()
        .getSecondReq(token)
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread()).singleElement()
        .subscribe({
                it-> mySecondReqLiveData.value = it
        },{
            errorSecondReqLiveData.value = it
        },{

        })
    compositeDisposable.add(SecondReqDisposable)

}

    override fun onCleared() {
    super.onCleared()
    compositeDisposable.clear()
}

}

and in my fragment, I implement this way:

class FirstTabFragment : Fragment() {
private lateinit var myViewModel: MyViewModel

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {

myViewModel = ViewModelProviders.of(activity!!).get(MyViewModel::class.java)

        getFirstReq(myViewModel, token!!)
        observeFirstReq(myViewModel)
        observeFirstReqError(myViewModel)

        observeSecondReq(myViewModel)
        observeSecondReqError(myViewModel)
}

    fun getFirstReq(viewModel: MyViewModel, token: String) {
    viewModel.getFirstReq(token)
}

   fun observeFirstReq(viewModel: MyViewModel) {
    viewModel.getFirstReqLiveData().observe(this, Observer { myFirstReqModel ->
   getSecondReq(myViewModel)
    }
   }

   fun getSecondReq(viewModel: MyViewModel, token: String) {
    viewModel.getSecondReq(token)
   }


    fun observeSecondReq(viewModel: MyViewModel) {
    viewModel.getSecondReqLiveData().observe(this, Observer { mySecondReqModel ->
   //do some work with my data
    }
   }

my problem is when I switch my tabs, my second request called several times.

I think I assign a new subscribe every time i reopen my fragment, so it called several times.

how can I fix this issue?!


Solution

  • Create below class

    open class Event<out T>(private val content: T) {
    
        var hasBeenHandled = false
            private set // Allow external read but not write
    
        /**
         * Returns the content and prevents its use again.
         */
        fun getContentIfNotHandled(): T? {
            return if (hasBeenHandled) {
                null
            } else {
                hasBeenHandled = true
                content
            }
        }
    
        /**
         * Returns the content, even if it's already been handled.
         */
        fun peekContent(): T = content
    }
    

    in Viewmodel change like this

    val myFirstReqLiveData = MutableLiveData<Event<myFirstReqModel>>()
    val mySecondReqLiveData = MutableLiveData<Event<mySecondReqModel>>()
    

    in Fragment class

    fun observeFirstReq(viewModel: MyViewModel) {
        viewModel.getFirstReqLiveData().observe(this, EventObserver { myFirstReqModel ->
       getSecondReq(myViewModel)
        }
       }
    

    change

    it-> myFirstReqLiveData.value = it to 
    it-> myFirstReqLiveData.value = Event(it)
    

    try using this way, if this helps you.