Android 在Kotlin中使用Flowable的多个翻新2请求

Android 在Kotlin中使用Flowable的多个翻新2请求,android,kotlin,retrofit2,rx-kotlin,Android,Kotlin,Retrofit2,Rx Kotlin,为了提高我在科特林的技能,我决定做一个演示项目。 演示项目包括在回收器视图中显示帖子,然后在详细信息活动中显示帖子的详细信息。 我在显示来自不同api调用的数据时遇到了困难:用户名、标题、文章正文和文章评论数 我的问题是,我希望执行多个请求,然后获得所需的所有数据,以便在详细信息活动中显示它们。这意味着打电话给我用户名,然后打电话给我帖子的评论数。文章的标题和正文来自主活动中完成的请求,我只是将其与包一起传输到详细活动 Api调用: //返回帖子1的评论 //返回用户2的信息 //用于在主活

为了提高我在科特林的技能,我决定做一个演示项目。 演示项目包括在回收器视图中显示帖子,然后在详细信息活动中显示帖子的详细信息。
我在显示来自不同api调用的数据时遇到了困难:用户名、标题、文章正文和文章评论数

我的问题是,我希望执行多个请求,然后获得所需的所有数据,以便在详细信息活动中显示它们。这意味着打电话给我用户名,然后打电话给我帖子的评论数。文章的标题和正文来自主活动中完成的请求,我只是将其与包一起传输到详细活动

Api调用:
//返回帖子1的评论

//返回用户2的信息

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

我还是Rx的新手,我想使用平面图,但我不知道如何在kotlin的Flowable中使用它

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)
                }
            }
        })
var post=viewModel.getPost()
var userStream:Flowable=postService.getUser(post.userId)
var commentsByPostIdCall:Flowable=postService.getCommentsByPostId(post.id)
userStream.subscribeOn(Schedulers.io())
.subscribe(对象:Subscriber){
覆盖有趣的错误(t:可丢弃?){
Log.d(this.toString(),“读取用户失败,并显示以下消息:”+t?.message);
}
覆盖下一页(用户:用户){
userTextView.text=user.name
title.text=post.title
body.text=post.body
}
覆盖有趣的onComplete(){
}
覆盖订阅的乐趣(s:订阅?){
如果(s!=null){
s、 请求(1)
}
}
})
我已将第二个调用放在方法getNumberComments中:

private fun getNumberComments(commentsByPostIdCall:Flowable):Int{
var listComments=listOf()
var listCommentSize=0
commentsByPostIdCall
.subscribeOn(Schedulers.io())
.subscribe(对象:Subscriber){
覆盖有趣的错误(t:可丢弃?){
Log.d(this.toString(),“读取注释失败,出现以下消息:”+t?.message);
}
覆盖下一页(注释:列表){
listComments=注释
}
覆盖有趣的onComplete(){
打印(“完成!”)
listCommentSize=listComments.size
}
覆盖订阅的乐趣(s:订阅?){
如果(s!=null){
s、 请求(1)
}
}
})
返回列表大小
}
我注意到的另一个想法是,有时流没有到达onComplete,有时流在onNext上仍然被阻塞。不明白为什么


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

这就是我解决问题的方法:

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")
      })
Kotlin有一个非常漂亮的lambda函数语法,因此我鼓励您将它们用于特定的subscribe函数:
订阅():
http://reactivex.io/RxJava/javadoc/io/reactivex/Flowable.html#subscribe(io.reactivex.functions.Consumer、%20io.reactivex.functions.Consumer、%20io.reactivex.functions.Action)

同样需要注意的是,我不仅使用了原始的Rxjava2库。我使用了以下LIB:
对于
observeOn(AndroidSchedulers.mainThread())
获取主线程。这是因为您在操作UI时没有指定订阅的线程。这样,您就可以在主线程上处理您的订阅。


对于
.bindToLifecycle(this)
如果活动已关闭,但您的改装2调用未完成,则这将确保您不会留下内存泄漏

我将如何解决此问题:

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")
      })
Kotlin有一个非常漂亮的lambda函数语法,因此我鼓励您将它们用于特定的subscribe函数:
订阅():
http://reactivex.io/RxJava/javadoc/io/reactivex/Flowable.html#subscribe(io.reactivex.functions.Consumer、%20io.reactivex.functions.Consumer、%20io.reactivex.functions.Action)

同样需要注意的是,我不仅使用了原始的Rxjava2库。我使用了以下LIB:
对于
observeOn(AndroidSchedulers.mainThread())
获取主线程。这是因为您在操作UI时没有指定订阅的线程。这样,您就可以在主线程上处理您的订阅。


对于
.bindToLifecycle(this)
如果活动已关闭,但您的改装2调用未完成,则这将确保您不会留下内存泄漏

我刚刚根据需要调整了Kioba建议的解决方案。我把这个贴在这里,以防对某人有用。 我不知道这是否是一种获取评论数量的优雅方式。我刚刚用List代替Comment,然后我做了一些类似的事情。second.size.toString()来获取注释数。
因为我只需要两个数据:user和comment,所以我决定使用Pair而不是Triple

Flowable.zip<User, List<Comment>, Pair<User, List<Comment>>>(
            postService.getUser(post.id),
            postService.getCommentsByPostId(post.id),
            BiFunction { user, comments -> Pair(user, comments) })
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .map { (first, second) -> Pair(first, second) }
            .subscribe({
                Log.d("MainActivity", "OnNext")
                userTextView.text = it.first.name
                title.text = post.title
                body.text = post.body
                number_comments.text = it.second.size.toString()

            }, {
                Log.d("MainActivity", "OnError")
            }, {
                Log.d("MainActivity", "OnComplete")
            }) 
Flowable.zip(
postService.getUser(post.id),
postService.getCommentsByPostId(post.id),
双功能{user,comments->Pair(user,comments)})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.map{(第一,第二)->对(第一,第二)}
.订阅({
Log.d(“main活动”、“OnNext”)
userTextView.text=it.first.name
Flowable.zip<User, List<Comment>, Pair<User, List<Comment>>>(
            postService.getUser(post.id),
            postService.getCommentsByPostId(post.id),
            BiFunction { user, comments -> Pair(user, comments) })
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .map { (first, second) -> Pair(first, second) }
            .subscribe({
                Log.d("MainActivity", "OnNext")
                userTextView.text = it.first.name
                title.text = post.title
                body.text = post.body
                number_comments.text = it.second.size.toString()

            }, {
                Log.d("MainActivity", "OnError")
            }, {
                Log.d("MainActivity", "OnComplete")
            })