``` class EmailViewModel(...) : ViewModel() { ...
# android-architecture
u
Copy code
class EmailViewModel(...) : ViewModel() {

    private val emailStateRelay = BehaviorRelay.createDefault(EmailState())
    val emailStateObservable: Observable<EmailState>
        get() = emailStateRelay
            .distinctUntilChanged()
            .observeOn(mainThreadScheduler)

    init {
        val messageByIdObservable = messageManager.emailMessageAndUsers(messageId)
            .replayingShare()

        disposables += messageByIdObservable
            .filterIsNull()
            .observeOn(mainThreadScheduler)
            .throwingSubscribe {
                navigator.goBack()
            }

        val messageByIdNonNullObservable = messageByIdObservable
            .filterNonNull()
            .replayingShare()

        disposables += messageByIdNonNullObservable
            .map { Optional(it.body) }
            .distinctUntilChanged()
            .switchMap {
                if (it.isEmpty()) {
                    messageManager.fetchEmailBody(messageId)
                        .asEvents()
                } else {
                    Observable.just(Event.Success(Unit))
                }
            }
            .throwingSubscribe { event ->
                when (event) {
                    is Event.Started -> {
                        emailStateRelay.accept {
                            it.copy(loading = true, error = null)
                        }
                    }
                    is Event.Success -> {
                        emailStateRelay.accept {
                            it.copy(loading = false, error = null)
                        }
                    }
                    is Event.Error -> {
                        emailStateRelay.accept {
                            it.copy(loading = false, error = event.value)
                        }
                    }
                }
            }

        disposables += messageByIdNonNullObservable
            .throwingSubscribe { message ->
                emailStateRelay.accept {
                    it.copy(
                        subject = message.subject,
                        fromUser = message.fromUser.toInviteUser(),
                        toUsers = message.toUsers.map { user -> user.toInviteUser() },
                        body = message.body?.let { body ->
                            HtmlCompat.fromHtml(body, HtmlCompat.FROM_HTML_MODE_LEGACY)
                        }
                    )
                }
            }
    }
}

data class EmailState(
    val subject: String? = null,
    val fromUser: InviteUser? = null,
    val toUsers: List<InviteUser> = emptyList(),
    val body: CharSequence? = null,
    val loading: Boolean = false,
    val error: Throwable? = null
)