在Kotlin中使用Flowable进行多个Retrofit2请求 [英] Multiple retrofit2 requests using Flowable in Kotlin

查看:801
本文介绍了在Kotlin中使用Flowable进行多个Retrofit2请求的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为了提高我在Kotlin,Rx和Retrofit2中的技能,我决定做一个演示项目. 该演示项目包括在回收者视图中显示帖子,然后在明细活动中显示帖子的详细信息.
我在显示来自不同api调用的数据时遇到了困难:用户名,标题,帖子的正文以及帖子的评论数.

In order to improve my skills in kotlin, Rx, Retrofit2 I've decided to do a demo project. The demo project consist to display posts in a recycler view then display details of the post in a detail activity.
I've encountered difficulties displaying data coming from different api call: the user name, the title, the body of the post and the number of comments of the post.

我的问题是我想执行多个请求,然后拥有所有必要的数据,以便在明细活动中显示它们.这意味着先打给我用户名的电话,再打给我发帖评论的电话.帖子的标题和正文来自主要活动中的请求,我只是将其与捆绑包一起发送到了详细活动.

My problem is that I would like to do multiple request and then have all the data needed in order to display them in the detail activity. Which mean doing a call that give me the user name and then a call that give me the number of comments for the post. The title and the body of the post are coming from a request done in the main activity I just transmit it with the bundle to the detail activity.

Api呼叫:
//返回帖子1的评论
http://jsonplaceholder.typicode.com/comments?postId=1

Api calls:
// return the comments for the post 1
http://jsonplaceholder.typicode.com/comments?postId=1

//返回用户2的信息
http://jsonplaceholder.typicode.com/users/2

// return the information of the user 2
http://jsonplaceholder.typicode.com/users/2

//用于在主要活动中显示帖子的呼叫
http:/jsonplaceholder.typicode.com/posts

// call used to display posts in the main activity
http:/jsonplaceholder.typicode.com/posts

我对Rx还是很陌生,我想使用flatMap,但是我不知道如何在kotlin中将它与Flowable一起使用.

I'm still new on Rx, I was thinking to use a flatMap but I don't know how to use it with Flowable in kotlin..

var post = viewModel.getPost()
var userStream: Flowable<User> = postService.getUser(post.userId)
var commentsByPostIdCall: Flowable<List<Comment>> = postService.getCommentsByPostId(post.id)

userStream.subscribeOn(Schedulers.io())
        .subscribe(object : Subscriber<User> {
            override fun onError(t: Throwable?) {
                Log.d(this.toString(), " Read of users failed with the following message: " + t?.message);
            }

            override fun onNext(user: User) {
                userTextView.text = user.name
                title.text = post.title
                body.text = post.body
            }

            override fun onComplete() {
            }

            override fun onSubscribe(s: Subscription?) {
                if (s != null) {
                    s.request(1)
                }
            }
        })

我已将第二个调用放在方法 getNumberComments 中:

I have put the second call in a method getNumberComments:

    private fun getNumberComments(commentsByPostIdCall: Flowable<List<Comment>>): Int {
    var listComments = listOf<Comment>()
    var listCommentSize = 0

     commentsByPostIdCall
             .subscribeOn(Schedulers.io())
             .subscribe(object : Subscriber<List<Comment>> {
                override fun onError(t: Throwable?) {
                    Log.d(this.toString(), " Read of comments failed with the following message: " + t?.message);
                }

                override fun onNext(comment: List<Comment>) {
                    listComments = comment
                }

                override fun onComplete() {
                    print("onComplete!")
                    listCommentSize = listComments.size
                }

                override fun onSubscribe(s: Subscription?) {
                    if (s != null) {
                        s.request(1)
                    }
                }
            })
    return listCommentSize

}

我认为我注意到的其他情况是,有时流没有进入onComplete,有时在onNext上仍然被阻塞.不明白为什么?

Other think that I've noticed is that sometimes the stream didn't go to onComplete, sometimes it remains blocked on onNext. Don't understand why?

任何帮助将不胜感激!非常感谢:)

Any help will be much appreciate! Thanks a lot :)

推荐答案

这就是我要解决的方式:

this is how i would solve it:

Flowable.zip<User, Comments, Pair<User, Comments>>(
      postService.getUser(postId),
      postService.getCommentsByPostId(postId),
      BiFunction { user, comments -> Pair(user, comments) })
      .subscribeOn(Schedulers.io())
      .observeOn(AndroidSchedulers.mainThread())
      .bindToLifecycle(this)
      .map { (first, second) -> Triple(first, second, ExtraDatasFromSomewhere) }
      .subscribe({
        Log.d("MainActivity", "OnNext")
      }, {
        Log.d("MainActivity", "OnError")
      }, {
        Log.d("MainActivity", "OnComplete")
      })

如果retrofit2调用彼此之间不互相pent悔,请使用zipzipWith函数实现您的目标.
您可以在此处找到更多信息:
RxZip():http://reactivex.io/documentation/operators/zip.

Use the zip or zipWith functions to achieve your goal if the retrofit2 calls dont depent on each other.
You can find out more here:
RxZip() : http://reactivex.io/documentation/operators/zip .

您可以像这样轻松地将来自服务器的数据与mainActivity数据一起映射:

You can easily map the data from the server with the mainActivity data together like this:

.map { (first, second) -> Triple(first, second, ExtraDatasFromSomewhere) }

Kotlin对于lambda函数具有非常漂亮的语法,因此我鼓励您将其与特定的subscription函数一起使用:
subscription():http://reactivex.io/RxJava/javadoc/io/reactivex/Flowable.html#subscribe(io.reactivex.functions.Consumer,%20io.reactivex.functions.Consumer,%20io.reactivex.functions.Action)

Kotlin has a very beautiful syntax for lambda functions so i would encourage you to use them with the specific subscribe function:
subscribe() : http://reactivex.io/RxJava/javadoc/io/reactivex/Flowable.html#subscribe(io.reactivex.functions.Consumer,%20io.reactivex.functions.Consumer,%20io.reactivex.functions.Action)

要特别注意的一点,我不只使用原始的Rxjava2库.我用下面的库: RxAndroid
observeOn(AndroidSchedulers.mainThread())获取mainThread.这是因为您在没有指定订阅线程的情况下操纵了UI.这样,您可以实现将在mainThread上处理您的订阅.
RxLifecycle
对于.bindToLifecycle(this),这将确保在活动关闭但您的retrofit2调用未完成的情况下,您不会留下内存泄漏

Also very important to note that i did not use only the raw Rxjava2 lib. i used the libs below: RxAndroid
for observeOn(AndroidSchedulers.mainThread()) to get the mainThread. This is because you manipulated the UI without specifying the thread you subscribed on. With this you can achieve that your subscription will be handled on the mainThread.
RxLifecycle
for .bindToLifecycle(this) this will make sure you don't leave memory leak if the activity is closed but your retrofit2 call did not finished

这篇关于在Kotlin中使用Flowable进行多个Retrofit2请求的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆