RxJava:从另一个异步生成中取消订阅异步observable

时间:2016-03-23 13:27:05

标签: rx-java kotlin

取消订阅另一个异步版Observable中的异步flatMap的最佳(干净)方法是什么? 说,我有一个演示文稿,显示用户的聊天列表。 每个聊天项目都应显示自己的最新消息。 这是一个原始代码来说明:

fun AsyncInsideAsync() {
    /**
     * A chat that 'transmits' latest message
     */
    class Chat(val name: Int) {
        val lastMessage: PublishSubject<String> = PublishSubject.create()

        fun postMessage(message: Int) {
            lastMessage.onNext("Chat: $name, Message: $message")
        }
    }

    // List of chats for user.
    val chats: PublishSubject<Chat> = PublishSubject.create()

    ///////////////////////////////////
    //        ORIGINAL SEQUENCE      //
    ///////////////////////////////////
    val sequence = chats.flatMap { it.lastMessage }

    val subscriber = TestSubscriber<String>()
    sequence.subscribe(subscriber)

    // User has single chat in a chat-list
    val chat1 = Chat(1)
    chats.onNext(chat1)

    // Someone posts a message in Chat 1
    chat1.postMessage(1)
    subscriber.assertValues(
            "Chat: 1, Message: 1"
    )

    // Someone posts another message
    chat1.postMessage(2)
    subscriber.assertValues(
            "Chat: 1, Message: 1",
            "Chat: 1, Message: 2"
    )

    // Chat 1 disappears FROM USER CHAT LIST, Chat 2 is created
    val chat2 = Chat(2)
    chats.onNext(chat2)

    // Someone posts a message to Chat 2
    chat2.postMessage(1)
    subscriber.assertValues(
            "Chat: 1, Message: 1",
            "Chat: 1, Message: 2",
            "Chat: 2, Message: 1"
    )

    // Someone out there posts a message to Chat 1 that is not visible to user anymore
    chat1.postMessage(3)

    // The answer looks like this 
    //      "Chat: 1, Message: 1",
    //      "Chat: 1, Message: 2",
    //      "Chat: 2, Message: 1",
    //      "Chat: 1, Message: 3"
    // Chat 1 is still subscribed and test fails
    subscriber.assertValues(
            "Chat: 1, Message: 1",
            "Chat: 1, Message: 2",
            "Chat: 2, Message: 1",
    )
}

我想到的是使用一个主题(或共享的可观察对象)来制造一系列内部订阅。但它看起来很奇怪:

    ///////////////////////////////////
    //        MODIFIED SEQUENCE      //
    ///////////////////////////////////
    val unsubscribe: PublishSubject<Boolean> = PublishSubject.create()
    val sequence = chats
            .doOnNext({ unsubscribe.onNext(true) })
            .doAfterTerminate({ unsubscribe.onNext(true) })
            .flatMap {
                it.lastMessage.takeUntil(unsubscribe)
            }

这种方法有效,但看起来很可怕。 非常感谢!

1 个答案:

答案 0 :(得分:2)

假设评论

// Chat 1 disappears FROM USER CHAT LIST, Chat 2 is created

表示您希望当前Chat(在这种情况下为chat1)在Chat上发送新的chats时停止发出,您可以使用switchMap运算符完成此操作。

val sequence = chats.switchMap { it.lastMessage }

来自ReactiveX文档:

  

RxJava还实现了switchMap运算符。它表现得很像   flatMap,除了源每次发出新项目   可观察,它将取消订阅并停止镜像Observable   这是从先前发出的项目生成的,仅从头开始   反映当前的一个。