{"id":319184,"date":"2021-03-07T21:00:27","date_gmt":"2021-03-07T21:00:27","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=319184"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=319184","title":{"rendered":"Reaction \u2014 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0432 Kotlin"},"content":{"rendered":"\n<div class=\"post__text post__text_v2\" id=\"post-content-body\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/268\/e12\/c98\/268e12c983579a6610008bfcc3a2542c.png\" width=\"1600\" height=\"440\"><figcaption><\/figcaption><\/figure>\n<p>\u041a\u0430\u0436\u0434\u044b\u0439, \u043a\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b <a href=\"https:\/\/blog.cleancoder.com\/uncle-bob\/2012\/08\/13\/the-clean-architecture.html\" rel=\"noopener noreferrer nofollow\">\u0427\u0438\u0441\u0442\u0443\u044e \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0443<\/a> \u0432 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435, \u0441\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u043b\u0441\u044f \u0441 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u043e\u0439 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u043c\u0435\u0436\u0434\u0443 \u0441\u043b\u043e\u044f\u043c\u0438. \u0421\u0443\u0442\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0432\u0441\u0435\u0433\u0434\u0430 \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u0430: \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0432\u0435\u0440\u043d\u0443\u0442\u044c \u043b\u0438\u0431\u043e \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442, \u043b\u0438\u0431\u043e \u043e\u0448\u0438\u0431\u043a\u0443. \u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u044d\u0442\u043e \u043c\u043e\u0436\u043d\u043e, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0442\u0430\u043a:<\/p>\n<pre><code class=\"kotlin\">interface Reaction  data class Success(val data: String) : Reaction data class Error(message: String) : Reaction<\/code><\/pre>\n<p>\u0412 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0437\u0430\u0434\u0430\u0447\u0438, \u0442\u0430\u043a\u0438\u0435 Reaction\u2019\u044b \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0441\u0430\u043c\u044b\u0435 \u0440\u0430\u0437\u043d\u044b\u0435, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0438\u043c \u0435\u0433\u043e \u0432 \u043e\u0434\u0438\u043d \u043a\u043b\u0430\u0441\u0441, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f <a href=\"https:\/\/kotlinlang.ru\/docs\/reference\/generics.html\" rel=\"noopener noreferrer nofollow\">Generics <\/a>\u0438 <a href=\"https:\/\/kotlinlang.org\/docs\/sealed-classes.html\" rel=\"noopener noreferrer nofollow\">Sealed class\u2019\u044b<\/a>.<\/p>\n<pre><code class=\"kotlin\">sealed class Reaction&lt;out T&gt; {    class Success&lt;out T&gt;(val data: T) : Reaction&lt;T&gt;()    class Error(val exception: Throwable) : Reaction&lt;Nothing&gt;() }<\/code><\/pre>\n<p>\u0420\u0430\u0437\u0431\u0435\u0440\u0435\u043c \u043f\u0440\u0438\u043c\u0435\u0440 \u043a\u0430\u043a \u044d\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c<\/p>\n<pre><code class=\"kotlin\">class MyViewModel : ViewModel { \tprivate val repository: Repository \t \tfun doSomething() { \t\tviewModelScope.launch(Dispatchers.IO) { \t\t\tval result = repository.getData() \t\t\twhen (result) { \t\t\t\tis Success -&gt; \/\/do something \t\t\t\tis Error -&gt; \/\/ show error \t\t\t} \t\t} \t} }<\/code><\/pre>\n<p>\u0412\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043d\u0435\u043f\u043b\u043e\u0445\u043e. \u041c\u044b \u043c\u043e\u0436\u0435\u043c \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0438 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u043e\u0448\u0438\u0431\u043a\u0443.<br \/>\u0422\u0435\u043f\u0435\u0440\u044c \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043a\u0430\u043a \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u0432 \u0442\u0435\u043a\u0443\u0449\u0435\u043c \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0435<\/p>\n<pre><code class=\"kotlin\">class RepositoryImpl(private val dataSource: DataSource) : Repository {    \toverride suspend fun getData(): Reaction&lt;Int&gt; { \t\treturn try { \t\t\tReaction.Success(dataSource.data) \t\t} catch(e: Exception) { \t\t\tReaction.Error(e) \t\t} \t} } <\/code><\/pre>\n<p>\u0418\u0437-\u0437\u0430 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u043a\u0430\u0436\u0434\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f \u0434\u043e\u043b\u0436\u0435\u043d \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c Reaction, \u043f\u0440\u0438\u0434\u0435\u0442\u0441\u044f \u043a\u0430\u0436\u0434\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 \u043e\u0431\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0442\u044c \u0432 try-catch, \u0447\u0442\u043e \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043d\u0435\u043a\u0440\u0430\u0441\u0438\u0432\u043e \u0438\u0437-\u0437\u0430 \u043e\u0433\u0440\u043e\u043c\u043d\u043e\u0433\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 <a href=\"https:\/\/en.wikipedia.org\/wiki\/Boilerplate_code#:~:text=In%20computer%20programming%2C%20boilerplate%20code,Such%20code%20is%20called%20boilerplate.\" rel=\"noopener noreferrer nofollow\">\u0431\u043e\u0439\u043b\u0435\u0440\u043f\u043b\u0435\u0439\u0442 \u043a\u043e\u0434\u0430.<\/a> \u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043a\u043e\u0434 \u0447\u0438\u0449\u0435, \u0432\u044b\u043d\u043e\u0441\u043e\u043c try-catch \u0432 \u043c\u0435\u0442\u043e\u0434.<\/p>\n<pre><code class=\"kotlin\">sealed class Reaction&lt;out T&gt; {     class Success&lt;out T&gt;(val data: T) : Reaction&lt;T&gt;()    class Error(val exception: Throwable) : Reaction&lt;Nothing&gt;()     companion object {        inline fun &lt;T&gt; on(f: () -&gt; T): Reaction&lt;T&gt; = try {            Success(f())        } catch (ex: Exception) {            Error(ex)        }    } }<\/code><\/pre>\n<p>\u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u043d\u0430\u0447\u043d\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0442\u0430\u043a:<\/p>\n<pre><code class=\"kotlin\">class RepositoryImpl(private val dataSource: DataSource) : Repository {  \tsuspend fun getData(): Reaction&lt;Int&gt; = Reaction.on { dataSource.data } }<\/code><\/pre>\n<p>\u0412\u0438\u0434\u043d\u043e, \u0447\u0442\u043e \u043a\u043e\u0434 \u0441\u0442\u0430\u043b \u0433\u043e\u0440\u0430\u0437\u0434\u043e \u0447\u0438\u0449\u0435 \u0438 \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u044d\u0442\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043c\u044b \u0441\u044d\u043a\u043e\u043d\u043e\u043c\u0438\u043b\u0438 4 \u0441\u0442\u0440\u043e\u043a\u0438 \u043a\u043e\u0434\u0430.<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0432\u0435\u0440\u043d\u0435\u043c\u0441\u044f \u043a <a href=\"https:\/\/developer.android.com\/topic\/libraries\/architecture\/viewmodel\" rel=\"noopener noreferrer nofollow\">ViewModel <\/a>\u0438 \u043f\u043e\u0441\u0442\u0430\u0440\u0430\u0435\u043c\u0441\u044f \u0443\u0431\u0440\u0430\u0442\u044c \u0431\u043e\u0439\u043b\u0435\u0440\u043f\u043b\u044d\u0439\u0442 when \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430. \u0421\u0435\u0439\u0447\u0430\u0441 \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0435, \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u043c \u0438 \u043e\u0442\u0434\u0430\u0435\u043c \u0432\u043e View.<\/p>\n<pre><code class=\"kotlin\">class MyViewModel : ViewModel { \tprivate val repository: Repository \tprivate val _onData = MutableLiveData&lt;State&gt;() \tval onData: LiveData&lt;State&gt; = _onData  \tfun doSomething() { \t\tviewModelScope.launch(Dispatchers.IO) { \t\t\tval result = repository.getData() \t\t\twhen (result) { \t\t\t\tis Success -&gt; _onData.postValue(State.Success) \t\t\t\tis Error -&gt; onData.postValue(State.Error(result.message)) \t\t\t} \t\t} \t}  \tsealed class State {   \tobject Progress : State()   \tobject Success : State()   \tdata class Error(message: String) : State() \t} }<\/code><\/pre>\n<p>\u0420\u0435\u0448\u0435\u043d\u0438\u0435 \u0443\u0436\u0435 \u043f\u043e\u0434\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u043e\u043f\u044b\u0442 <a href=\"https:\/\/github.com\/ReactiveX\/RxJava\" rel=\"noopener noreferrer nofollow\">RxJava<\/a>, <a href=\"https:\/\/developer.android.com\/kotlin\/coroutines\" rel=\"noopener noreferrer nofollow\">Coroutines <\/a>\u0438 <a href=\"https:\/\/developer.android.com\/topic\/libraries\/architecture\/livedata\" rel=\"noopener noreferrer nofollow\">LiveData<\/a>.<br \/>\u0418\u0441\u0445\u043e\u0434\u044f \u0438\u0437 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u0434\u0430\u043d\u043d\u044b\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0435\u0440\u043d\u0443\u043b\u0438\u0441\u044c \u0432 <a href=\"https:\/\/developer.android.com\/topic\/libraries\/architecture\/viewmodel\" rel=\"noopener noreferrer nofollow\">ViewModel <\/a>\u043e\u0431\u044b\u0447\u043d\u043e \u043d\u0430\u0434\u043e \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u0432 \u0432\u0438\u0434\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u0430, \u043b\u0438\u0431\u043e \u043e\u0448\u0438\u0431\u043a\u0438, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043c\u0435\u0442\u043e\u0434 zip, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442\u044c Reaction \u043a \u043e\u0431\u044a\u0435\u043a\u0442\u0443, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c\u0441\u044f \u0432 LiveData<\/p>\n<pre><code class=\"kotlin\">inline fun &lt;T, R&gt; Result&lt;T&gt;.zip(success: (T) -&gt; R, error: (Exception) -&gt; R): R =    when (this) {        is Reaction.Success -&gt; success(this.data)        is Reaction.Error -&gt; error(this.exception)    }<\/code><\/pre>\n<p>\u041d\u0430\u0448\u0430 <em>MyViewModel \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0438\u0442\u0441\u044f \u0432 <\/em><\/p>\n<pre><code class=\"kotlin\">class MyViewModel : ViewModel { \tprivate val repository: Repository \tprivate val _onData = MutableLiveData&lt;State&gt;() \tval onData: LiveData&lt;State&gt; = _onNewDirectory  \tfun doSomething() { \t\tviewModelScope.launch(Dispatchers.IO) { \t\t\trepository.getData() \t\t\t\t.zip(         \t{ State.Success },          \t{ State.Error(result.message) }         ) \t\t\t\t.let { onData.postValue(it) } \t\t} \t}  \t\/\/... }<\/code><\/pre>\n<p>\u0422\u0430\u043a\u0436\u0435 \u0435\u0441\u0442\u044c \u0447\u0430\u0441\u0442\u044b\u0439 \u0441\u043b\u0443\u0447\u0430\u0439, \u043a\u043e\u0433\u0434\u0430 \u043c\u0435\u0442\u043e\u0434 \u0432 ViewModel \u0434\u0435\u043b\u0430\u0435\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043a \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044e, \u0433\u0434\u0435 \u043e\u0434\u043d\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u0437\u0430\u0432\u0438\u0441\u044f\u0442 \u043e\u0442 \u0440\u0430\u043d\u0435\u0435 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0445. \u041f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 \u043e\u0448\u0438\u0431\u043a\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u0440\u0435\u0440\u0432\u0430\u0442\u044c \u0446\u0435\u043f\u043e\u0447\u043a\u0443 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0438 \u0432\u0435\u0440\u043d\u0443\u0442\u044c \u043e\u0448\u0438\u0431\u043a\u0443 \u0432\u043e View<\/p>\n<p>\u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043f\u0440\u0438\u043c\u0435\u0440:<\/p>\n<pre><code class=\"kotlin\">class MyViewModel : ViewModel { \t\/\/... \tfun doSomething() { \t\tviewModelScope.launch(Dispatchers.IO) { \t\t\tvar firstData: Int = 0  \t\t\tval reaction = repository.getData() \t\t\twhen (reaction) { \t\t\t\tis Success -&gt; firstData = reaction.data  \t\t\t\tis Error -&gt; { \t\t\t\t\tonData.postValue(State.Error(reaction.message)) \t\t\t\t\treturn@launch \t\t\t\t} \t\t\t}  \t\t\tval nextReaction = repository.getNextData(firstData)        \t\t\t\/\/.. \t\t}\t\t \t}    \t\/\/... }<\/code><\/pre>\n<p>\u0420\u0435\u0448\u0435\u043d\u0438\u0439 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0438\u0434\u0443\u043c\u0430\u0442\u044c \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e, \u043d\u043e \u044f \u0437\u0434\u0435\u0441\u044c \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044e \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0431\u0435\u0437 <a href=\"http:\/\/callbackhell.com\/\" rel=\"noopener noreferrer nofollow\">callback hell<\/a>, \u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044f \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u043e, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 <a href=\"https:\/\/developer.android.com\/kotlin\/coroutines\" rel=\"noopener noreferrer nofollow\">Coroutines<\/a><\/p>\n<pre><code class=\"kotlin\">class MyViewModel : ViewModel {   \/\/... \tfun doSomething() { \t\tviewModelScope.launch(Dispatchers.IO) { \t\t\tval firstData = repository.getData() \t\t\t\t.takeOrReturn { \t\t\t\t\tonData.postValue(State.Error(result.message) \t\t\t\t\treturn@launch \t\t\t\t} \t\t\tval nextReaction= repository.getNextData(firstData)        \t\t\t\/\/.. \t\t}\t\t \t} }<\/code><\/pre>\n<p>\u0412 \u0438\u0442\u043e\u0433\u0435 \u043c\u044b \u0438\u043c\u0435\u0435\u043c \u043b\u0435\u0433\u043a\u043e \u0440\u0430\u0441\u0448\u0438\u0440\u044f\u0435\u043c\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0443\u0436\u0435 \u0435\u0441\u0442\u044c \u0442\u0430\u043a\u0438\u0435 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u043a\u0430\u043a:<\/p>\n<ul>\n<li>\n<p><strong>on <\/strong>&#8212; \u0421\u043e\u0437\u0434\u0430\u0435\u0442 Reaction \u0438\u0437 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f<\/p>\n<\/li>\n<li>\n<p><strong>map <\/strong>&#8212; \u0422\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u0442 \u0443\u0441\u043f\u0435\u0448\u043d\u044b\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442<\/p>\n<\/li>\n<li>\n<p><strong>flatMap <\/strong>&#8212; \u0422\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u0442 \u0443\u0441\u043f\u0435\u0448\u043d\u044b\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432 \u043d\u043e\u0432\u0443\u044e Reaction<\/p>\n<\/li>\n<li>\n<p><strong>doOnSuccess <\/strong>&#8212; \u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f, \u0435\u0441\u043b\u0438 Reaction &#8212; \u0443\u0441\u043f\u0435\u0448\u043d\u044b\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442<\/p>\n<\/li>\n<li>\n<p>\u0438 \u0434\u0440<\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u043e\u043b\u043d\u044b\u0439 \u0441\u043f\u0438\u0441\u043e\u043a \u0438 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 \u0432 <a href=\"https:\/\/github.com\/taptappub\/Reaction\/\" rel=\"noopener noreferrer nofollow\"><strong>Github<\/strong><\/a><\/p>\n<h2>\u0421\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435 \u0441 \u0430\u043d\u0430\u043b\u043e\u0433\u0430\u043c\u0438<\/h2>\n<p>\u0411\u044b\u043b\u043e \u043d\u0430\u0439\u0434\u0435\u043d\u043e 3 \u0430\u043d\u0430\u043b\u043e\u0433\u0430. \u041d\u0438\u0436\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u044b \u0441\u0430\u043c\u0438 \u0430\u043d\u0430\u043b\u043e\u0433\u0438 \u0438 \u0438\u0445 \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u0430 \u0438 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043a\u0438<\/p>\n<ul>\n<li>\n<p><a href=\"https:\/\/proandroiddev.com\/railway-oriented-programming-in-kotlin-f1bceed399e5\" rel=\"noopener noreferrer nofollow\">Railway Kotlin<\/a> <br \/><strong>\u041f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u0430<\/strong>:<\/p>\n<ul>\n<li>\n<p>\u041b\u0435\u0433\u043a\u043e \u043e\u0441\u0432\u043e\u0438\u0442\u044c<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 1 \u0444\u0430\u0439\u043b\u0430<\/p>\n<\/li>\n<\/ul>\n<p><strong>\u041d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043a\u0438<\/strong>:<\/p>\n<ul>\n<li>\n<p>\u041d\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0438\u043d\u043a\u0430\u043f\u0441\u0443\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c try-catch<\/p>\n<\/li>\n<li>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 infix \u043c\u0435\u0442\u043e\u0434\u043e\u0432<\/p>\n<\/li>\n<li>\n<p>\u041d\u0435\u0438\u043d\u0442\u0443\u0438\u0442\u0438\u0432\u043d\u044b\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f \u043c\u0435\u0442\u043e\u0434\u043e\u0432<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><a href=\"https:\/\/arrow-kt.io\/\" rel=\"noopener noreferrer nofollow\">Arrow-KT<\/a><br \/><strong>\u041f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u0430<\/strong>:<\/p>\n<ul>\n<li>\n<p>\u041f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u0430\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430<\/p>\n<\/li>\n<\/ul>\n<p><strong>\u041d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043a\u0438<\/strong>:<\/p>\n<ul>\n<li>\n<p>\u0418\u0437 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043d\u0435\u043f\u043e\u043d\u044f\u0442\u043d\u043e \u0447\u0442\u043e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u043c\u043e\u0436\u0435\u0442<\/p>\n<\/li>\n<li>\n<p>\u0412\u044b\u0441\u043e\u043a\u0438\u0439 \u043f\u043e\u0440\u043e\u0433 \u0432\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u043f\u043e \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044e \u0441 \u0430\u043d\u0430\u043b\u043e\u0433\u0430\u043c\u0438<\/p>\n<\/li>\n<li>\n<p>\u041e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043e\u0449\u0443\u0449\u0435\u043d\u0438\u0435, \u0447\u0442\u043e \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u0441\u043b\u043e\u0436\u043d\u043e\u0439 \u0434\u043b\u044f \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0442\u0430\u043a\u043e\u0439 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><a href=\"https:\/\/github.com\/Kotlin\/KEEP\/blob\/master\/proposals\/stdlib\/result.md\" rel=\"noopener noreferrer nofollow\">Result (Kotlin) <\/a><br \/><strong>\u041f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u0430<\/strong>:<\/p>\n<ul>\n<li>\n<p>\u042f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u043e\u0447\u0442\u0438 \u043f\u043e\u043b\u043d\u043e\u0439 \u043a\u043e\u043f\u0438\u0435\u0439 \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u043c\u043e\u0433\u043e \u043c\u043d\u043e\u0439 \u0440\u0435\u0448\u0435\u043d\u0438\u044f<\/p>\n<\/li>\n<\/ul>\n<p><strong>\u041d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043a\u0438<\/strong>:<\/p>\n<ul>\n<li>\n<p><a href=\"https:\/\/github.com\/Kotlin\/KEEP\/blob\/master\/proposals\/stdlib\/result.md#limitations\" rel=\"noopener noreferrer nofollow\">\u041d\u0435\u043b\u044c\u0437\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u0430\u043a \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435<\/a><\/p>\n<\/li>\n<li>\n<p>\u041c\u043e\u0436\u043d\u043e <a href=\"https:\/\/stackoverflow.com\/questions\/52631827\/why-cant-kotlin-result-be-used-as-a-return-type\" rel=\"noopener noreferrer nofollow\">\u0432\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435<\/a> \u0432 gradle, \u043d\u043e \u043d\u0430 \u0441\u0432\u043e\u0439 \u0441\u0442\u0440\u0430\u0445 \u0438 \u0440\u0438\u0441\u043a, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e Result, \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0447\u0430\u0441\u0442\u044c\u044e \u044f\u0437\u044b\u043a\u0430 Kotlin \u0438 \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u043c\u0435\u043d\u044f\u0442\u044c \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h2>\u0418\u0442\u043e\u0433<\/h2>\n<p><strong>Reaction <\/strong>&#8212; \u044d\u0442\u043e \u043b\u0435\u0433\u043a\u043e\u0432\u0435\u0441\u043d\u0430\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0441 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u043c \u043f\u043e\u0440\u043e\u0433\u043e\u043c \u0432\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f, \u0442.\u043a. \u043e\u043d\u0430 \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 1 \u0444\u0430\u0439\u043b\u0430, \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0449\u0430\u044f \u0442\u0430\u043a\u0438\u0435 \u0436\u0435 \u043c\u043e\u0449\u043d\u043e\u0441\u0442\u0438, \u043a\u0430\u043a \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043e\u0442 Kotlin, \u043d\u043e \u043d\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0432\u0441\u0435\u0445 \u0435\u0433\u043e \u043c\u0438\u043d\u0443\u0441\u043e\u0432.<\/p>\n<h2>GitHub<\/h2>\n<p><a href=\"https:\/\/github.com\/taptappub\/Reaction\/\" rel=\"noopener noreferrer nofollow\">https:\/\/github.com\/taptappub\/Reaction\/<\/a><\/p>\n<\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/post\/545926\/\"> https:\/\/habr.com\/ru\/post\/545926\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"\n<div class=\"post__text post__text_v2\" id=\"post-content-body\">\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u041a\u0430\u0436\u0434\u044b\u0439, \u043a\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b <a href=\"https:\/\/blog.cleancoder.com\/uncle-bob\/2012\/08\/13\/the-clean-architecture.html\" rel=\"noopener noreferrer nofollow\">\u0427\u0438\u0441\u0442\u0443\u044e \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0443<\/a> \u0432 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435, \u0441\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u043b\u0441\u044f \u0441 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u043e\u0439 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u043c\u0435\u0436\u0434\u0443 \u0441\u043b\u043e\u044f\u043c\u0438. \u0421\u0443\u0442\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0432\u0441\u0435\u0433\u0434\u0430 \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u0430: \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0432\u0435\u0440\u043d\u0443\u0442\u044c \u043b\u0438\u0431\u043e \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442, \u043b\u0438\u0431\u043e \u043e\u0448\u0438\u0431\u043a\u0443. \u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u044d\u0442\u043e \u043c\u043e\u0436\u043d\u043e, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0442\u0430\u043a:<\/p>\n<pre><code class=\"kotlin\">interface Reaction  data class Success(val data: String) : Reaction data class Error(message: String) : Reaction<\/code><\/pre>\n<p>\u0412 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0437\u0430\u0434\u0430\u0447\u0438, \u0442\u0430\u043a\u0438\u0435 Reaction\u2019\u044b \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0441\u0430\u043c\u044b\u0435 \u0440\u0430\u0437\u043d\u044b\u0435, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0438\u043c \u0435\u0433\u043e \u0432 \u043e\u0434\u0438\u043d \u043a\u043b\u0430\u0441\u0441, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f <a href=\"https:\/\/kotlinlang.ru\/docs\/reference\/generics.html\" rel=\"noopener noreferrer nofollow\">Generics <\/a>\u0438 <a href=\"https:\/\/kotlinlang.org\/docs\/sealed-classes.html\" rel=\"noopener noreferrer nofollow\">Sealed class\u2019\u044b<\/a>.<\/p>\n<pre><code class=\"kotlin\">sealed class Reaction&lt;out T&gt; {    class Success&lt;out T&gt;(val data: T) : Reaction&lt;T&gt;()    class Error(val exception: Throwable) : Reaction&lt;Nothing&gt;() }<\/code><\/pre>\n<p>\u0420\u0430\u0437\u0431\u0435\u0440\u0435\u043c \u043f\u0440\u0438\u043c\u0435\u0440 \u043a\u0430\u043a \u044d\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c<\/p>\n<pre><code class=\"kotlin\">class MyViewModel : ViewModel { \tprivate val repository: Repository \t \tfun doSomething() { \t\tviewModelScope.launch(Dispatchers.IO) { \t\t\tval result = repository.getData() \t\t\twhen (result) { \t\t\t\tis Success -&gt; \/\/do something \t\t\t\tis Error -&gt; \/\/ show error \t\t\t} \t\t} \t} }<\/code><\/pre>\n<p>\u0412\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043d\u0435\u043f\u043b\u043e\u0445\u043e. \u041c\u044b \u043c\u043e\u0436\u0435\u043c \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0438 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u043e\u0448\u0438\u0431\u043a\u0443.<br \/>\u0422\u0435\u043f\u0435\u0440\u044c \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043a\u0430\u043a \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u0432 \u0442\u0435\u043a\u0443\u0449\u0435\u043c \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0435<\/p>\n<pre><code class=\"kotlin\">class RepositoryImpl(private val dataSource: DataSource) : Repository {    \toverride suspend fun getData(): Reaction&lt;Int&gt; { \t\treturn try { \t\t\tReaction.Success(dataSource.data) \t\t} catch(e: Exception) { \t\t\tReaction.Error(e) \t\t} \t} } <\/code><\/pre>\n<p>\u0418\u0437-\u0437\u0430 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u043a\u0430\u0436\u0434\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f \u0434\u043e\u043b\u0436\u0435\u043d \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c Reaction, \u043f\u0440\u0438\u0434\u0435\u0442\u0441\u044f \u043a\u0430\u0436\u0434\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 \u043e\u0431\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0442\u044c \u0432 try-catch, \u0447\u0442\u043e \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043d\u0435\u043a\u0440\u0430\u0441\u0438\u0432\u043e \u0438\u0437-\u0437\u0430 \u043e\u0433\u0440\u043e\u043c\u043d\u043e\u0433\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 <a href=\"https:\/\/en.wikipedia.org\/wiki\/Boilerplate_code#:~:text=In%20computer%20programming%2C%20boilerplate%20code,Such%20code%20is%20called%20boilerplate.\" rel=\"noopener noreferrer nofollow\">\u0431\u043e\u0439\u043b\u0435\u0440\u043f\u043b\u0435\u0439\u0442 \u043a\u043e\u0434\u0430.<\/a> \u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043a\u043e\u0434 \u0447\u0438\u0449\u0435, \u0432\u044b\u043d\u043e\u0441\u043e\u043c try-catch \u0432 \u043c\u0435\u0442\u043e\u0434.<\/p>\n<pre><code class=\"kotlin\">sealed class Reaction&lt;out T&gt; {     class Success&lt;out T&gt;(val data: T) : Reaction&lt;T&gt;()    class Error(val exception: Throwable) : Reaction&lt;Nothing&gt;()     companion object {        inline fun &lt;T&gt; on(f: () -&gt; T): Reaction&lt;T&gt; = try {            Success(f())        } catch (ex: Exception) {            Error(ex)        }    } }<\/code><\/pre>\n<p>\u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u043d\u0430\u0447\u043d\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0442\u0430\u043a:<\/p>\n<pre><code class=\"kotlin\">class RepositoryImpl(private val dataSource: DataSource) : Repository {  \tsuspend fun getData(): Reaction&lt;Int&gt; = Reaction.on { dataSource.data } }<\/code><\/pre>\n<p>\u0412\u0438\u0434\u043d\u043e, \u0447\u0442\u043e \u043a\u043e\u0434 \u0441\u0442\u0430\u043b \u0433\u043e\u0440\u0430\u0437\u0434\u043e \u0447\u0438\u0449\u0435 \u0438 \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u044d\u0442\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043c\u044b \u0441\u044d\u043a\u043e\u043d\u043e\u043c\u0438\u043b\u0438 4 \u0441\u0442\u0440\u043e\u043a\u0438 \u043a\u043e\u0434\u0430.<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0432\u0435\u0440\u043d\u0435\u043c\u0441\u044f \u043a <a href=\"https:\/\/developer.android.com\/topic\/libraries\/architecture\/viewmodel\" rel=\"noopener noreferrer nofollow\">ViewModel <\/a>\u0438 \u043f\u043e\u0441\u0442\u0430\u0440\u0430\u0435\u043c\u0441\u044f \u0443\u0431\u0440\u0430\u0442\u044c \u0431\u043e\u0439\u043b\u0435\u0440\u043f\u043b\u044d\u0439\u0442 when \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430. \u0421\u0435\u0439\u0447\u0430\u0441 \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0435, \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u043c \u0438 \u043e\u0442\u0434\u0430\u0435\u043c \u0432\u043e View.<\/p>\n<pre><code class=\"kotlin\">class MyViewModel : ViewModel { \tprivate val repository: Repository \tprivate val _onData = MutableLiveData&lt;State&gt;() \tval onData: LiveData&lt;State&gt; = _onData  \tfun doSomething() { \t\tviewModelScope.launch(Dispatchers.IO) { \t\t\tval result = repository.getData() \t\t\twhen (result) { \t\t\t\tis Success -&gt; _onData.postValue(State.Success) \t\t\t\tis Error -&gt; onData.postValue(State.Error(result.message)) \t\t\t} \t\t} \t}  \tsealed class State {   \tobject Progress : State()   \tobject Success : State()   \tdata class Error(message: String) : State() \t} }<\/code><\/pre>\n<p>\u0420\u0435\u0448\u0435\u043d\u0438\u0435 \u0443\u0436\u0435 \u043f\u043e\u0434\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u043e\u043f\u044b\u0442 <a href=\"https:\/\/github.com\/ReactiveX\/RxJava\" rel=\"noopener noreferrer nofollow\">RxJava<\/a>, <a href=\"https:\/\/developer.android.com\/kotlin\/coroutines\" rel=\"noopener noreferrer nofollow\">Coroutines <\/a>\u0438 <a href=\"https:\/\/developer.android.com\/topic\/libraries\/architecture\/livedata\" rel=\"noopener noreferrer nofollow\">LiveData<\/a>.<br \/>\u0418\u0441\u0445\u043e\u0434\u044f \u0438\u0437 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u0434\u0430\u043d\u043d\u044b\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0435\u0440\u043d\u0443\u043b\u0438\u0441\u044c \u0432 <a href=\"https:\/\/developer.android.com\/topic\/libraries\/architecture\/viewmodel\" rel=\"noopener noreferrer nofollow\">ViewModel <\/a>\u043e\u0431\u044b\u0447\u043d\u043e \u043d\u0430\u0434\u043e \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u0432 \u0432\u0438\u0434\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u0430, \u043b\u0438\u0431\u043e \u043e\u0448\u0438\u0431\u043a\u0438, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043c\u0435\u0442\u043e\u0434 zip, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442\u044c Reaction \u043a \u043e\u0431\u044a\u0435\u043a\u0442\u0443, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c\u0441\u044f \u0432 LiveData<\/p>\n<pre><code class=\"kotlin\">inline fun &lt;T, R&gt; Result&lt;T&gt;.zip(success: (T) -&gt; R, error: (Exception) -&gt; R): R =    when (this) {        is Reaction.Success -&gt; success(this.data)        is Reaction.Error -&gt; error(this.exception)    }<\/code><\/pre>\n<p>\u041d\u0430\u0448\u0430 <em>MyViewModel \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0438\u0442\u0441\u044f \u0432 <\/em><\/p>\n<pre><code class=\"kotlin\">class MyViewModel : ViewModel { \tprivate val repository: Repository \tprivate val _onData = MutableLiveData&lt;State&gt;() \tval onData: LiveData&lt;State&gt; = _onNewDirectory  \tfun doSomething() { \t\tviewModelScope.launch(Dispatchers.IO) { \t\t\trepository.getData() \t\t\t\t.zip(         \t{ State.Success },          \t{ State.Error(result.message) }         ) \t\t\t\t.let { onData.postValue(it) } \t\t} \t}  \t\/\/... }<\/code><\/pre>\n<p>\u0422\u0430\u043a\u0436\u0435 \u0435\u0441\u0442\u044c \u0447\u0430\u0441\u0442\u044b\u0439 \u0441\u043b\u0443\u0447\u0430\u0439, \u043a\u043e\u0433\u0434\u0430 \u043c\u0435\u0442\u043e\u0434 \u0432 ViewModel \u0434\u0435\u043b\u0430\u0435\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043a \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044e, \u0433\u0434\u0435 \u043e\u0434\u043d\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u0437\u0430\u0432\u0438\u0441\u044f\u0442 \u043e\u0442 \u0440\u0430\u043d\u0435\u0435 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0445. \u041f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 \u043e\u0448\u0438\u0431\u043a\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u0440\u0435\u0440\u0432\u0430\u0442\u044c \u0446\u0435\u043f\u043e\u0447\u043a\u0443 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0438 \u0432\u0435\u0440\u043d\u0443\u0442\u044c \u043e\u0448\u0438\u0431\u043a\u0443 \u0432\u043e View<\/p>\n<p>\u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043f\u0440\u0438\u043c\u0435\u0440:<\/p>\n<pre><code class=\"kotlin\">class MyViewModel : ViewModel { \t\/\/... \tfun doSomething() { \t\tviewModelScope.launch(Dispatchers.IO) { \t\t\tvar firstData: Int = 0  \t\t\tval reaction = repository.getData() \t\t\twhen (reaction) { \t\t\t\tis Success -&gt; firstData = reaction.data  \t\t\t\tis Error -&gt; { \t\t\t\t\tonData.postValue(State.Error(reaction.message)) \t\t\t\t\treturn@launch \t\t\t\t} \t\t\t}  \t\t\tval nextReaction = repository.getNextData(firstData)        \t\t\t\/\/.. \t\t}\t\t \t}    \t\/\/... }<\/code><\/pre>\n<p>\u0420\u0435\u0448\u0435\u043d\u0438\u0439 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0438\u0434\u0443\u043c\u0430\u0442\u044c \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e, \u043d\u043e \u044f \u0437\u0434\u0435\u0441\u044c \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044e \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0431\u0435\u0437 <a href=\"http:\/\/callbackhell.com\/\" rel=\"noopener noreferrer nofollow\">callback hell<\/a>, \u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044f \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u043e, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 <a href=\"https:\/\/developer.android.com\/kotlin\/coroutines\" rel=\"noopener noreferrer nofollow\">Coroutines<\/a><\/p>\n<pre><code class=\"kotlin\">class MyViewModel : ViewModel {   \/\/... \tfun doSomething() { \t\tviewModelScope.launch(Dispatchers.IO) { \t\t\tval firstData = repository.getData() \t\t\t\t.takeOrReturn { \t\t\t\t\tonData.postValue(State.Error(result.message) \t\t\t\t\treturn@launch \t\t\t\t} \t\t\tval nextReaction= repository.getNextData(firstData)        \t\t\t\/\/.. \t\t}\t\t \t} }<\/code><\/pre>\n<p>\u0412 \u0438\u0442\u043e\u0433\u0435 \u043c\u044b \u0438\u043c\u0435\u0435\u043c \u043b\u0435\u0433\u043a\u043e \u0440\u0430\u0441\u0448\u0438\u0440\u044f\u0435\u043c\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0443\u0436\u0435 \u0435\u0441\u0442\u044c \u0442\u0430\u043a\u0438\u0435 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u043a\u0430\u043a:<\/p>\n<ul>\n<li>\n<p><strong>on <\/strong>&#8212; \u0421\u043e\u0437\u0434\u0430\u0435\u0442 Reaction \u0438\u0437 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f<\/p>\n<\/li>\n<li>\n<p><strong>map <\/strong>&#8212; \u0422\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u0442 \u0443\u0441\u043f\u0435\u0448\u043d\u044b\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442<\/p>\n<\/li>\n<li>\n<p><strong>flatMap <\/strong>&#8212; \u0422\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u0442 \u0443\u0441\u043f\u0435\u0448\u043d\u044b\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432 \u043d\u043e\u0432\u0443\u044e Reaction<\/p>\n<\/li>\n<li>\n<p><strong>doOnSuccess <\/strong>&#8212; \u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f, \u0435\u0441\u043b\u0438 Reaction &#8212; \u0443\u0441\u043f\u0435\u0448\u043d\u044b\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442<\/p>\n<\/li>\n<li>\n<p>\u0438 \u0434\u0440<\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u043e\u043b\u043d\u044b\u0439 \u0441\u043f\u0438\u0441\u043e\u043a \u0438 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 \u0432 <a href=\"https:\/\/github.com\/taptappub\/Reaction\/\" rel=\"noopener noreferrer nofollow\"><strong>Github<\/strong><\/a><\/p>\n<h2>\u0421\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435 \u0441 \u0430\u043d\u0430\u043b\u043e\u0433\u0430\u043c\u0438<\/h2>\n<p>\u0411\u044b\u043b\u043e \u043d\u0430\u0439\u0434\u0435\u043d\u043e 3 \u0430\u043d\u0430\u043b\u043e\u0433\u0430. \u041d\u0438\u0436\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u044b \u0441\u0430\u043c\u0438 \u0430\u043d\u0430\u043b\u043e\u0433\u0438 \u0438 \u0438\u0445 \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u0430 \u0438 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043a\u0438<\/p>\n<ul>\n<li>\n<p><a href=\"https:\/\/proandroiddev.com\/railway-oriented-programming-in-kotlin-f1bceed399e5\" rel=\"noopener noreferrer nofollow\">Railway Kotlin<\/a> <br \/><strong>\u041f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u0430<\/strong>:<\/p>\n<ul>\n<li>\n<p>\u041b\u0435\u0433\u043a\u043e \u043e\u0441\u0432\u043e\u0438\u0442\u044c<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 1 \u0444\u0430\u0439\u043b\u0430<\/p>\n<\/li>\n<\/ul>\n<p><strong>\u041d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043a\u0438<\/strong>:<\/p>\n<ul>\n<li>\n<p>\u041d\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0438\u043d\u043a\u0430\u043f\u0441\u0443\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c try-catch<\/p>\n<\/li>\n<li>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 infix \u043c\u0435\u0442\u043e\u0434\u043e\u0432<\/p>\n<\/li>\n<li>\n<p>\u041d\u0435\u0438\u043d\u0442\u0443\u0438\u0442\u0438\u0432\u043d\u044b\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f \u043c\u0435\u0442\u043e\u0434\u043e\u0432<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><a href=\"https:\/\/arrow-kt.io\/\" rel=\"noopener noreferrer nofollow\">Arrow-KT<\/a><br \/><strong>\u041f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u0430<\/strong>:<\/p>\n<ul>\n<li>\n<p>\u041f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u0430\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430<\/p>\n<\/li>\n<\/ul>\n<p><strong>\u041d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043a\u0438<\/strong>:<\/p>\n<ul>\n<li>\n<p>\u0418\u0437 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043d\u0435\u043f\u043e\u043d\u044f\u0442\u043d\u043e \u0447\u0442\u043e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u043c\u043e\u0436\u0435\u0442<\/p>\n<\/li>\n<li>\n<p>\u0412\u044b\u0441\u043e\u043a\u0438\u0439 \u043f\u043e\u0440\u043e\u0433 \u0432\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u043f\u043e \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044e \u0441 \u0430\u043d\u0430\u043b\u043e\u0433\u0430\u043c\u0438<\/p>\n<\/li>\n<li>\n<p>\u041e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043e\u0449\u0443\u0449\u0435\u043d\u0438\u0435, \u0447\u0442\u043e \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u0441\u043b\u043e\u0436\u043d\u043e\u0439 \u0434\u043b\u044f \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0442\u0430\u043a\u043e\u0439 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><a href=\"https:\/\/github.com\/Kotlin\/KEEP\/blob\/master\/proposals\/stdlib\/result.md\" rel=\"noopener noreferrer nofollow\">Result (Kotlin) <\/a><br \/><strong>\u041f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u0430<\/strong>:<\/p>\n<ul>\n<li>\n<p>\u042f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u043e\u0447\u0442\u0438 \u043f\u043e\u043b\u043d\u043e\u0439 \u043a\u043e\u043f\u0438\u0435\u0439 \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u043c\u043e\u0433\u043e \u043c\u043d\u043e\u0439 \u0440\u0435\u0448\u0435\u043d\u0438\u044f<\/p>\n<\/li>\n<\/ul>\n<p><strong>\u041d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043a\u0438<\/strong>:<\/p>\n<ul>\n<li>\n<p><a href=\"https:\/\/github.com\/Kotlin\/KEEP\/blob\/master\/proposals\/stdlib\/result.md#limitations\" rel=\"noopener noreferrer nofollow\">\u041d\u0435\u043b\u044c\u0437\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u0430\u043a \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435<\/a><\/p>\n<\/li>\n<li>\n<p>\u041c\u043e\u0436\u043d\u043e <a href=\"https:\/\/stackoverflow.com\/questions\/52631827\/why-cant-kotlin-result-be-used-as-a-return-type\" rel=\"noopener noreferrer nofollow\">\u0432\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435<\/a> \u0432 gradle, \u043d\u043e \u043d\u0430 \u0441\u0432\u043e\u0439 \u0441\u0442\u0440\u0430\u0445 \u0438 \u0440\u0438\u0441\u043a, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e Result, \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0447\u0430\u0441\u0442\u044c\u044e \u044f\u0437\u044b\u043a\u0430 Kotlin \u0438 \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u043c\u0435\u043d\u044f\u0442\u044c \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h2>\u0418\u0442\u043e\u0433<\/h2>\n<p><strong>Reaction <\/strong>&#8212; \u044d\u0442\u043e \u043b\u0435\u0433\u043a\u043e\u0432\u0435\u0441\u043d\u0430\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0441 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u043c \u043f\u043e\u0440\u043e\u0433\u043e\u043c \u0432\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f, \u0442.\u043a. \u043e\u043d\u0430 \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 1 \u0444\u0430\u0439\u043b\u0430, \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0449\u0430\u044f \u0442\u0430\u043a\u0438\u0435 \u0436\u0435 \u043c\u043e\u0449\u043d\u043e\u0441\u0442\u0438, \u043a\u0430\u043a \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043e\u0442 Kotlin, \u043d\u043e \u043d\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0432\u0441\u0435\u0445 \u0435\u0433\u043e \u043c\u0438\u043d\u0443\u0441\u043e\u0432.<\/p>\n<h2>GitHub<\/h2>\n<p><a href=\"https:\/\/github.com\/taptappub\/Reaction\/\" rel=\"noopener noreferrer nofollow\">https:\/\/github.com\/taptappub\/Reaction\/<\/a><\/p>\n<\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/post\/545926\/\"> https:\/\/habr.com\/ru\/post\/545926\/<\/a><br \/><\/br><\/br><\/li>\n<\/ul>\n<\/p>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-319184","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/319184","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=319184"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/319184\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=319184"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=319184"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=319184"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}