title: Performance comparison: Mapping a LiveData value vs Flow value
body: <p>Currently, I am experimenting a bit with livedata and flow in android. What I stumbeld upon is, whether there are big performance differences when it comes to mapping a livedata value and a flow value because livedata mapping is performed in the main ui thread:</p>
  <pre><code>/**
   * Returns a [LiveData] mapped from `this` LiveData by applying [transform] to each value set on
   * `this` LiveData.
   *
   * This method is analogous to [io.reactivex.Observable.map].
   *
   * [transform] will be executed on the main thread.
   *
   * [...]
   **/
  public inline fun &lt;X, Y&gt; LiveData&lt;X&gt;.map(crossinline transform: (X) -&gt; Y): LiveData&lt;Y&gt; =
      Transformations.map(this) { transform(it) }
  </code></pre>
  <p>Now comes the trickery part: Let's assume we have a livedata value we want to map. Since mapping is performaned in the ui-thread, we convert the livedata value to a flow value:</p>
  <pre><code>public fun &lt;T&gt; LiveData&lt;T&gt;.asFlow(): Flow&lt;T&gt; = flow {
      val channel = Channel&lt;T&gt;(Channel.CONFLATED)
      val observer = Observer&lt;T&gt; {
          channel.offer(it)
      }
      withContext(Dispatchers.Main.immediate) {
          observeForever(observer)
      }
      try {
          for (value in channel) {
              emit(value)
          }
      } finally {
          GlobalScope.launch(Dispatchers.Main.immediate) {
              removeObserver(observer)
          }
      }
  }
  </code></pre>
  <p>After converting the livedata observer to a flow, we map the values successfully in another thread (Dispatchers.IO). But now we don't need a flow for the ui, so we convert it back to a livedata value:</p>
  <pre><code>@JvmOverloads
  public fun &lt;T&gt; Flow&lt;T&gt;.asLiveData(
      context: CoroutineContext = EmptyCoroutineContext,
      timeoutInMs: Long = DEFAULT_TIMEOUT
  ): LiveData&lt;T&gt; = liveData(context, timeoutInMs) {
      collect {
          emit(it)
      }
  }
  </code></pre>
  <p>Now the questions:</p>
  <ol>
  <li>Does mapping a livedata value has big performance impact in comparison to mapping a flow value</li>
  <li>Does converting a livedata value to a flow value and then converting it back to livedata introduce any overhead and or performance issues? If yes, would it be better to directly map the livedata value?</li>
  </ol>
  <p>A mapping example would be:</p>
  <pre><code>fun LiveData&lt;WorkInfo&gt;.collectStatus(): LiveData&lt;Status&lt;Unit&gt;&gt; = map { workInfo -&gt;
      when(workInfo.state) {
          WorkInfo.State.ENQUEUED -&gt; Status.loading()
  
          WorkInfo.State.RUNNING -&gt; Status.loading()
  
          WorkInfo.State.SUCCEEDED -&gt; Status.success(Unit)
  
          WorkInfo.State.BLOCKED -&gt; Status.failed(&quot;Workmanager blocked&quot;)
  
          WorkInfo.State.FAILED -&gt; Status.failed(&quot;Workmanager failed&quot;)
  
          WorkInfo.State.CANCELLED -&gt; Status.failed(&quot;Workmanager cancelled&quot;)
      }
  }
  </code></pre>