1

kotlin、Rx、Retrofit2 のスキルを向上させるために、デモ プロジェクトを行うことにしました。デモ プロジェクトは、リサイクラー ビューで投稿を表示し、詳細アクティビティで投稿の詳細を表示することで構成されます。
ユーザー名、タイトル、投稿の本文、投稿のコメント数など、さまざまな API 呼び出しからのデータを表示する際に問題が発生しました。

私の問題は、複数のリクエストを行い、詳細アクティビティに表示するために必要なすべてのデータを取得したいということです。つまり、ユーザー名を取得するための呼び出しを行い、次に投稿に対するコメントの数を取得するための呼び出しを行うということです。投稿のタイトルと本文は、メイン アクティビティで行われたリクエストから来ています。バンドルと一緒に詳細アクティビティに送信するだけです。

API 呼び出し:
// 投稿 1 のコメントを返します
http://jsonplaceholder.typicode.com/comments?postId=1

// ユーザー 2 の情報を返す
http://jsonplaceholder.typicode.com/users/2

// メイン アクティビティで投稿を表示するために使用される呼び出し
http://jsonplaceholder.typicode.com/posts

私はまだ Rx の初心者です。flatMap を使用することを考えていましたが、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)
                }
            }
        })

メソッドgetNumberCommentsに 2 番目の呼び出しを入れました。

    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でブロックされたままになることもあると思います。理由がわからない?

どんな助けでも大歓迎です!どうもありがとう :)

4

2 に答える 2

4

これは私がそれを解決する方法です:

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 呼び出しが互いに依存していない場合は、zipまたは関数を使用して目標を達成します。 詳細については、 RxZip() :を参照してください。zipWith

http://reactivex.io/documentation/operators/zip

次のように、サーバーからのデータを mainActivity データと一緒に簡単にマップできます。

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

Kotlin にはラムダ関数の非常に美しい構文があるため、特定のサブスクライブ関数で使用することをお勧めします:
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 だけを使用したのではないことに注意することも非常に重要です。以下のライブラリを使用しました: mainThread
observeOn(AndroidSchedulers.mainThread())取得するための RxAndroid。これは、購読しているスレッドを指定せずに UI を操作したためです。これにより、サブスクリプションが mainThread で処理されるようになります。 このための
RxLifecycleは、アクティビティが閉じられているが、retrofit2 呼び出しが終了していない場合に、メモリ リークを残さないようにします。
.bindToLifecycle(this)

于 2017-08-04T08:41:15.977 に答える