{"id":303347,"date":"2020-05-10T21:00:36","date_gmt":"2020-05-10T21:00:36","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=303347"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=303347","title":{"rendered":"\u041f\u0440\u043e\u0431\u0443\u0435\u043c \u0438 \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u0435\u043c\u0441\u044f \u0441 StateFlow"},"content":{"rendered":"\n<div class=\"post__text post__text-html post__text_v1\" id=\"post-content-body\" data-io-article-url=\"https:\/\/habr.com\/ru\/post\/501308\/\">\u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442.<\/p>\n<p>  \u041d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0434\u043d\u0435\u0439 \u043d\u0430\u0437\u0430\u0434 JetBrains \u0432\u044b\u043f\u0443\u0441\u0442\u0438\u043b <a href=\"https:\/\/github.com\/Kotlin\/kotlinx.coroutines\/releases\" rel=\"nofollow\">\u043d\u043e\u0432\u0443\u044e \u0432\u0435\u0440\u0441\u0438\u044e \u043a\u043e\u0440\u0443\u0442\u0438\u043d \u2014 1.3.6<\/a> \u0438 \u043e\u0434\u043d\u0438\u043c \u0438\u0437 \u043d\u043e\u0432\u043e\u0432\u0432\u0435\u0434\u0435\u043d\u0438\u0438 \u0441\u0442\u0430\u043b \u043d\u043e\u0432\u044b\u0439 \u043f\u043e\u0434\u0432\u0438\u0434 Flow \u2014 StateFlow, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 \u043d\u0430 \u0437\u0430\u043c\u0435\u043d\u0443 ConflatedBroadcastChannel. \u042f \u0440\u0435\u0448\u0438\u043b \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c StateFlow \u0432 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0438 \u0438 \u0438\u0437\u0443\u0447\u0438\u0442\u044c \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u0435 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e.<br \/>  <a name=\"habracut\"><\/a><br \/>  \u0414\u0443\u043c\u0430\u044e \u043c\u043d\u043e\u0433\u0438\u0435, \u043a\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u041a\u043e\u0442\u043b\u0438\u043d \u043f\u0440\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u043f\u043e\u0434 \u0410\u043d\u0434\u0440\u043e\u0438\u0434 \u0438\u043b\u0438 \u0432 MPP \u0437\u043d\u0430\u043a\u043e\u043c\u044b \u0441 \u044d\u0442\u0438\u043c\u0438 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043c\u0438, \u043a\u0442\u043e \u043d\u0435\u0442 \u2014 \u0434\u0430\u043d\u043d\u044b\u0435 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0431\u043b\u0438\u0437\u043a\u0438\u043c\u0438 \u0430\u043d\u0430\u043b\u043e\u0433\u0430\u043c\u0438 BehaviorProcessor\/BehaviorSubject \u0438\u0437 RxJava \u0438 LiveData\/MutableLiveData \u0438\u0437 Jetpack.<\/p>\n<p>  \u0421\u0430\u043c \u043f\u043e \u0441\u0435\u0431\u0435 StateFlow \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u043e\u0441\u0442\u044b\u043c \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435\u043c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 Flow \u0438 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u0432 \u0434\u0432\u0443\u0445 \u0432\u0438\u0434\u0430\u0445:<\/p>\n<pre><code class=\"kotlin\">public interface StateFlow&lt;out T&gt; : Flow&lt;T&gt; {     \/**      * The current value of this state flow.      *\/     public val value: T }  public interface MutableStateFlow&lt;T&gt; : StateFlow&lt;T&gt; {     \/**      * The current value of this state flow.      *      * Setting a value that is [equal][Any.equals] to the previous one does nothing.      *\/     public override var value: T } <\/code><\/pre>\n<p>  \u0418\u0434\u0435\u044f \u0442\u0430\u043a\u0430\u044f \u0436\u0435 \u043a\u0430\u043a \u0438 \u0443 LiveData\/MutableLiveData \u2014 \u0447\u0435\u0440\u0435\u0437 \u043e\u0434\u0438\u043d \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043c\u043e\u0436\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435, \u0430 \u0447\u0435\u0440\u0435\u0437 \u0434\u0440\u0443\u0433\u043e\u0439 \u0435\u0449\u0451 \u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c.<\/p>\n<p>  \u0427\u0442\u043e \u0436\u0435 \u043d\u0430\u043c \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u0442 StateFlow \u043f\u043e \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044e \u0441 ConflatedBroadcastChannel:<\/p>\n<ul>\n<li> \u0411\u043e\u043b\u0435\u0435 \u043f\u0440\u043e\u0441\u0442\u0430\u044f \u0438 garbage-free \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u044f\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f. <\/li>\n<li> \u041d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u044c \u043d\u0430\u043b\u0438\u0447\u0438\u044f \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u043f\u043e-\u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e. Null \u0442\u0430\u043a\u0436\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u0435\u043d. <\/li>\n<li> \u0420\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043d\u0430 read-only \u0438 read-write \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u044b. <\/li>\n<li> \u0421\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u0447\u0435\u0440\u0435\u0437 equality \u0432\u043c\u0435\u0441\u0442\u043e \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f \u0441\u0441\u044b\u043b\u043e\u043a. <\/li>\n<\/ul>\n<p>  \u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0442\u0435\u043f\u0435\u0440\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0441\u0442\u043e\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 StateFlow. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u044f \u0441\u0434\u0435\u043b\u0430\u043b \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u0440\u043d\u0443\u044e \u043e\u0431\u0451\u0440\u0442\u043a\u0443 \u0441 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u043b\u044e\u0431\u043e\u0439 \u0442\u0438\u043f \u0441 null \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u043c \u043f\u043e-\u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e:<\/p>\n<pre><code class=\"kotlin\">class StateFlowRepository&lt;T&gt;(initialValue: T? = null) {     private val stateFlow = MutableStateFlow(initialValue)      var value: T?         get() = stateFlow.value         set(value) {             stateFlow.value = value         }      val stream: Flow&lt;T?&gt; = stateFlow } <\/code><\/pre>\n<p>  \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0435:<\/p>\n<pre><code class=\"kotlin\">lifecycleScope.launch {             simpleRepo.stream.collect {                 addData(it.toString())             }         } <\/code><\/pre>\n<p>  \u0418 \u0432\u044b\u0432\u043e\u0434\u0438\u043c \u043d\u0430 \u044d\u043a\u0440\u0430\u043d \u0441 \u043f\u0440\u043e\u0441\u0442\u0435\u0439\u0448\u0438\u043c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u043c \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u043e\u0432, \u043d\u0438\u043a\u0430\u043a\u0438\u0445 \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u044d\u0442\u043e \u043d\u0435 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 \u0438 \u0432\u0441\u0451 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043a\u0430\u043a \u0447\u0430\u0441\u044b:<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/pn\/cv\/_c\/pncv_c41cwncgwkfc3hd3wxzfh0.png\"><\/p>\n<p>  \u0417\u0430\u0433\u043b\u044f\u043d\u0435\u043c \u0442\u0435\u043f\u0435\u0440\u044c \u0432\u043d\u0443\u0442\u0440\u044c \u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u043a\u0430\u043a \u044d\u0442\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043e.<\/p>\n<p>  \u041a \u043c\u043e\u0435\u043c\u0443 \u0443\u0434\u0438\u0432\u043b\u0435\u043d\u0438\u044e \u2014 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043e\u0447\u0435\u043d\u044c \u043f\u0440\u043e\u0441\u0442\u0430\u044f \u0438 \u0437\u0430\u043d\u044f\u043b\u0430 \u043d\u0430 \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u0432\u0441\u0435\u0433\u043e 316 \u0441\u0442\u0440\u043e\u0447\u0435\u043a, \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 25% \u2014 \u0434\u0436\u0430\u0432\u0430\u0434\u043e\u043a\u0438.<\/p>\n<p>  \u0418 \u0442\u0430\u043a, \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u043c \u043a\u043b\u0430\u0441\u0441\u043e\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043a\u043b\u0430\u0441\u0441 StateFlowImpl:<\/p>\n<pre><code class=\"kotlin\">private class StateFlowImpl&lt;T&gt;(initialValue: Any) : SynchronizedObject(), MutableStateFlow&lt;T&gt;, FusibleFlow&lt;T&gt; {     private val _state = atomic(initialValue) \/\/ T | NULL     private var sequence = 0 \/\/ serializes updates, value update is in process when sequence is odd     private var slots = arrayOfNulls&lt;StateFlowSlot?&gt;(INITIAL_SIZE)     private var nSlots = 0 \/\/ number of allocated (!free) slots     private var nextIndex = 0 \/\/ oracle for the next free slot index  . . . } <\/code><\/pre>\n<p>  <b>_state<\/b> \u2014 \u0430\u0442\u043e\u043c\u0438\u043a \u0441\u0441\u044b\u043b\u043a\u0430 \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u043d\u0430\u0448\u0435\u0433\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f.<\/p>\n<p>  <b>sequence<\/b> \u2014 \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u0438\u043d\u0434\u0438\u043a\u0430\u0442\u043e\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0447\u0451\u0442\u043d\u043e\u0441\u0442\u0438\/\u043d\u0435\u0447\u0451\u0442\u043d\u043e\u0441\u0442\u0438 \u0441\u043e\u043e\u0431\u0449\u0430\u0435\u0442 \u043e \u0442\u0435\u043a\u0443\u0449\u0435\u043c \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f<br \/>  <b>slots<\/b> \u2014 \u043c\u0430\u0441\u0441\u0438\u0432\/\u043f\u0443\u043b StateFlowSlot. StateFlowSlot \u2014 \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0446\u0438\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u00ab\u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f\u00bb \u043a StateFlow.<br \/>  <b>nSlots, nextIndex<\/b> \u2014 \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0440\u0430\u0441\u0448\u0438\u0440\u044f\u0435\u043c\u044b\u043c \u043c\u0430\u0441\u0441\u0438\u0432\u043e\u043c slots<\/p>\n<p>  \u0417\u0430\u0440\u0430\u043d\u0435\u0435 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c StateFlowSlot. \u041e\u043d \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u0441\u0435\u0433\u043e \u043d\u0430\u0432\u0441\u0435\u0433\u043e:<\/p>\n<pre><code class=\"kotlin\">private val _state = atomic&lt;Any?&gt;(null) <\/code><\/pre>\n<p>  \u041f\u043b\u044e\u0441 \u043c\u0435\u0442\u043e\u0434\u044b \u0434\u043b\u044f \u0441\u043c\u0435\u043d\u044b \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0439 \u0441\u043b\u043e\u0442\u0430.<\/p>\n<p>  \u041a\u0430\u0436\u0434\u044b\u0439 \u0441\u043b\u043e\u0442 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0432 \u043e\u0434\u043d\u043e\u043c \u0438\u0437 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0439:<\/p>\n<p>  <b>null<\/b> \u2014 \u0441\u043e\u0437\u0434\u0430\u043d, \u043d\u043e \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f<br \/>  <b>NONE<\/b> \u2014 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043a\u043e\u043b\u043b\u0435\u043a\u0442\u043e\u0440\u043e\u043c<br \/>  <b>PENDING<\/b> \u2014 \u0432 \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u043d\u043e\u0432\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432 \u043a\u043e\u043b\u043b\u0435\u043a\u0442\u043e\u0440<br \/>  <b>CancellableContinuationImpl<\/b> \u2014 \u0441\u0430\u0441\u043f\u0435\u043d\u0434\u0435\u0434 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435, \u0431\u043b\u0438\u0437\u043a\u043e\u0435 \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0441 PENDING, \u043f\u043e\u0434\u0432\u0435\u0448\u0438\u0432\u0430\u0435\u043c \u043a\u043e\u043b\u043b\u0435\u043a\u0442\u043e\u0440 \u043f\u043e\u043a\u0430 \u043d\u0435 \u043f\u0440\u0438\u0434\u0451\u0442 \u043d\u043e\u0432\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0432 StateFlow.<\/p>\n<p>  \u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u0447\u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043f\u0440\u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0435 \u043d\u043e\u0432\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f:<\/p>\n<pre><code class=\"kotlin\">public override var value: T         get() = NULL.unbox(_state.value)         set(value) {             var curSequence = 0             var curSlots: Array&lt;StateFlowSlot?&gt; = this.slots \/\/ benign race, we will not use it             val newState = value ?: NULL             synchronized(this) {                 val oldState = _state.value                 if (oldState == newState) return \/\/ Don't do anything if value is not changing                 _state.value = newState                 curSequence = sequence                 if (curSequence and 1 == 0) { \/\/ even sequence means quiescent state flow (no ongoing update)                     curSequence++ \/\/ make it odd                     sequence = curSequence                 } else {                     \/\/ update is already in process, notify it, and return                     sequence = curSequence + 2 \/\/ change sequence to notify, keep it odd                     return                 }                 curSlots = slots \/\/ read current reference to collectors under lock             }             \/*                Fire value updates outside of the lock to avoid deadlocks with unconfined coroutines                Loop until we're done firing all the changes. This is sort of simple flat combining that                ensures sequential firing of concurrent updates and avoids the storm of collector resumes                when updates happen concurrently from many threads.              *\/             while (true) {                 \/\/ Benign race on element read from array                 for (col in curSlots) {                     col?.makePending()                 }                 \/\/ check if the value was updated again while we were updating the old one                 synchronized(this) {                     if (sequence == curSequence) { \/\/ nothing changed, we are done                         sequence = curSequence + 1 \/\/ make sequence even again                         return \/\/ done                     }                     \/\/ reread everything for the next loop under the lock                     curSequence = sequence                     curSlots = slots                 }             }         } <\/code><\/pre>\n<p>  \u041e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u0437\u0430\u0434\u0430\u0447\u0430 \u0437\u0434\u0435\u0441\u044c \u2014 \u0443\u0441\u0442\u0430\u043a\u0430\u043d\u0438\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f StateFlow \u0438\u0437 \u0440\u0430\u0437\u043d\u044b\u0445 \u043f\u043e\u0442\u043e\u043a\u043e\u0432 \u0434\u043b\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0432\u044b\u0437\u043e\u0432\u043e\u0432 FlowCollector.<\/p>\n<p>  \u041c\u043e\u0436\u043d\u043e \u0432\u044b\u0434\u0435\u043b\u0438\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0448\u0430\u0433\u043e\u0432:<\/p>\n<ol>\n<li>\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u043d\u043e\u0432\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f.<\/li>\n<li>\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u043c\u0430\u0440\u043a\u0435\u0440\u0430 sequence \u2014 \u0432 \u043d\u0435\u0447\u0451\u0442\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043e\u0431\u043e\u0437\u043d\u0430\u0447\u0430\u044e\u0449\u0435\u0435, \u0447\u0442\u043e \u043c\u044b \u0443\u0436\u0435 \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0430\u043f\u0434\u0435\u0439\u0442\u0430.<\/li>\n<li>makePending() \u2014 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0432\u0441\u0435\u0445 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0439 \u0441\u043b\u043e\u0442\u043e\u0432(\u0442.\u0435. \u0432\u0441\u0435\u0445 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0439) \u0432 PENDING \u2014 \u0441\u043a\u043e\u0440\u043e \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u043c \u043d\u043e\u0432\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435.<\/li>\n<li>\u0426\u0438\u043a\u043b \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 sequence == curSequence, \u0447\u0442\u043e \u0432\u0441\u0435 \u0437\u0430\u0434\u0430\u0447\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u044b \u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 sequence \u0447\u0451\u0442\u043d\u044b\u043c \u0447\u0438\u0441\u043b\u043e\u043c.<\/li>\n<\/ol>\n<p>  \u0427\u0442\u043e \u0436\u0435 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0432 \u043c\u0435\u0442\u043e\u0434\u0435 <b>collect<\/b>:<\/p>\n<pre><code class=\"kotlin\">override suspend fun collect(collector: FlowCollector&lt;T&gt;) {         val slot = allocateSlot()         var prevState: Any? = null \/\/ previously emitted T!! | NULL (null -- nothing emitted yet)         try {             \/\/ The loop is arranged so that it starts delivering current value without waiting first             while (true) {                 \/\/ Here the coroutine could have waited for a while to be dispatched,                 \/\/ so we use the most recent state here to ensure the best possible conflation of stale values                 val newState = _state.value                 \/\/ Conflate value emissions using equality                 if (prevState == null || newState != prevState) {                     collector.emit(NULL.unbox(newState))                     prevState = newState                 }                 \/\/ Note: if awaitPending is cancelled, then it bails out of this loop and calls freeSlot                 if (!slot.takePending()) { \/\/ try fast-path without suspending first                     slot.awaitPending() \/\/ only suspend for new values when needed                 }             }         } finally {             freeSlot(slot)         }     } <\/code><\/pre>\n<p>  \u041e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u0437\u0430\u0434\u0430\u0447\u0430 \u2014 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0438 \u0436\u0434\u0430\u0442\u044c \u043d\u043e\u0432\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f: <\/p>\n<ol>\n<li>\u0421\u043e\u0437\u0434\u0430\u0451\u043c \u0438\u043b\u0438 \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0441\u043b\u043e\u0442 \u043d\u043e\u0432\u043e\u0433\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f.<\/li>\n<li>\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043d\u0430 null \u0438\u043b\u0438 \u043d\u0430 \u0441\u043c\u0435\u043d\u0443 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f. \u042d\u043c\u0438\u0442\u0442\u0438\u043c \u043d\u043e\u0432\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435.<\/li>\n<li>\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0435\u0441\u0442\u044c \u043b\u0438 \u0441\u043b\u043e\u0442\u044b \u0433\u043e\u0442\u043e\u0432\u044b\u0435 \u0434\u043b\u044f \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f (PENDING \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435) \u0438 \u0435\u0441\u043b\u0438 \u043d\u0435\u0442 \u2014 \u043f\u043e\u0434\u0432\u0435\u0448\u0438\u0432\u0430\u0435\u043c \u0441\u043b\u043e\u0442 \u0432 \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u0438 \u043d\u043e\u0432\u044b\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439.<\/li>\n<\/ol>\n<p>  \u0412 \u0446\u0435\u043b\u043e\u043c, \u044d\u0442\u043e \u0432\u0441\u0451. \u041c\u044b \u043d\u0435 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043b\u0438, \u043a\u0430\u043a \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0430\u043b\u043b\u043e\u043a\u0430\u0446\u0438\u0438 \u0441\u043b\u043e\u0442\u043e\u0432 \u0438 \u0441\u043c\u0435\u043d\u0430 \u0438\u0445 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0439, \u043d\u043e \u044f \u043f\u043e\u0441\u0447\u0438\u0442\u0430\u043b, \u0447\u0442\u043e \u0434\u043b\u044f \u043e\u0431\u0449\u0435\u0439 \u043a\u0430\u0440\u0442\u0438\u043d\u044b StateFlow \u044d\u0442\u043e \u043d\u0435 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0438\u0430\u043b\u044c\u043d\u043e.<\/p>\n<p>  \u0421\u043f\u0430\u0441\u0438\u0431\u043e.<\/p><\/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\/501308\/\"> https:\/\/habr.com\/ru\/post\/501308\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"\n<div class=\"post__text post__text-html post__text_v1\" id=\"post-content-body\" data-io-article-url=\"https:\/\/habr.com\/ru\/post\/501308\/\">\u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442.<\/p>\n<p>  \u041d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0434\u043d\u0435\u0439 \u043d\u0430\u0437\u0430\u0434 JetBrains \u0432\u044b\u043f\u0443\u0441\u0442\u0438\u043b <a href=\"https:\/\/github.com\/Kotlin\/kotlinx.coroutines\/releases\" rel=\"nofollow\">\u043d\u043e\u0432\u0443\u044e \u0432\u0435\u0440\u0441\u0438\u044e \u043a\u043e\u0440\u0443\u0442\u0438\u043d \u2014 1.3.6<\/a> \u0438 \u043e\u0434\u043d\u0438\u043c \u0438\u0437 \u043d\u043e\u0432\u043e\u0432\u0432\u0435\u0434\u0435\u043d\u0438\u0438 \u0441\u0442\u0430\u043b \u043d\u043e\u0432\u044b\u0439 \u043f\u043e\u0434\u0432\u0438\u0434 Flow \u2014 StateFlow, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 \u043d\u0430 \u0437\u0430\u043c\u0435\u043d\u0443 ConflatedBroadcastChannel. \u042f \u0440\u0435\u0448\u0438\u043b \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c StateFlow \u0432 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0438 \u0438 \u0438\u0437\u0443\u0447\u0438\u0442\u044c \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u0435 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e.  <\/p>\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-303347","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/303347","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=303347"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/303347\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=303347"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=303347"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=303347"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}