使用 rxJava 和改造多次调用另一个请求中的请求

Posted

技术标签:

【中文标题】使用 rxJava 和改造多次调用另一个请求中的请求【英文标题】:request in another request called several times with rxJava and retrofit 【发布时间】:2020-01-29 22:28:00 【问题描述】:

我正在使用 MVVM 和 rxJava 和改造来发送我的请求。 我有一个底部导航视图,其中有 5 个片段,在其中一个片段中,我必须发送一个请求,然后发送响应,我必须向我的服务器发送另一个请求。 这是我的 ViewModel 类:

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()



在我的片段中,我是这样实现的:

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
    
   

我的问题是当我切换标签时,我的第二个请求被调用了多次。

我想我每次重新打开我的片段时都会分配一个新的订阅,所以它调用了几次。

我该如何解决这个问题?!

【问题讨论】:

getFirstReqLiveData 在您切换选项卡时收到通知。由于它正在为第二个请求进行 API 调用。您必须将可变的实时数据包装到 Event 中,并且在片段中,您必须作为 EventObserver 进行观察 @KishanMaurya 你能解释更多吗?我是新手,我不知道如何实现你所说的 如果发布的代码对你有用,请告诉我.. 否则分享代码,我会调试并告诉你原因 【参考方案1】:

在下面创建类

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

在 Viewmodel 中像这样更改

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

在片段类中

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

改变

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

如果对您有帮助,请尝试使用这种方式。

【讨论】:

你也可以分享EventObserver的课程吗?! class EventObserver(private val onEventUnhandledContent: (T) -> Unit) : Observer> override fun onChanged(event: Event?) event?. getContentIfNotHandled()?.let value -> onEventUnhandledContent(value) 欢迎您.. :) :) 您可以在互联网上了解事件和事件观察者。【参考方案2】:

您还可以从观察者中删除 getSecondReq(myViewModel) 并组合或链接您的请求。

https://github.com/ReactiveX/RxJava/wiki/Combining-Observables

类似这样的:

    val disposable = RetrofitClientInstance.getRetrofitInterface()
        .getFirstReq(token)
        .doOnError  errorFirstReqLiveData.value = it 
        .doOnNext  myFirstReqLiveData.value = it 
        .flatMap  t -> getSecondReq(token) 
        .doOnError  errorSecondReqLiveData.value = it 
        .doOnNext  mySecondReqLiveData.value = it 
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread()).singleElement()
        .subscribe()
compositeDisposable.add(disposable)

【讨论】:

我是 RxJava 新手,我会阅读并在未来使用您的答案,谢谢 @AzinNilchi 不客气 :) 这个链接非常有用,我经常查看它以查看所有可用选项

以上是关于使用 rxJava 和改造多次调用另一个请求中的请求的主要内容,如果未能解决你的问题,请参考以下文章

使用改造对 mvvm 中的 Rxjava 进行错误处理

带有 rxJava2 和改造的 UndeliverableException

使用 Kotlin 进行 RxJava 和改造

如何使用 RXJava 调用的响应结果作为另一个 RXJava 函数中的 if 语句的条件?

Rxjava 2 - 使用领域和改造获取数据

改造获取多个请求的最后一个请求