title: How to implement a full repository with kotlin flow
body: <p>I'm trying to implement a full repository using room's new flow support and retrofit's coroutine support. I'm running in some issues that I don't seem to find a solution to.</p>
  
  <p>So first, let's state where i got so far. This is my ViewModel class:</p>
  
  <pre><code>class InvViewModel : ViewModel() {
  val repo = Repository()
  
  val flow = flow {
      emit(Lce.Loading())
      val result = repo.updateInv()
      repo.getInv().collect { inv -&gt;
          result?.let { exception -&gt;
              emit(Lce.Error&lt;List&lt;Inv&gt;&gt;(inv, exception))
          } ?: emit(Lce.Content(inv))
      }
  }
  
  fun getLocalInv() = flow.asLiveData()
  
  fun updateInv() =
      viewModelScope.launch {
          repo.updateInv()
      }
  }
  </code></pre>
  
  <p>In this class, I create a flow that sets a state of loading, requests remote data from network, when it gets a result it subscribes to the Room Database and it transforms the flow automatically returned from the DB to a flow that knows the state of the network call as well as the data from the db.</p>
  
  <p>What is wrong with this and what i don't seem to be able to fix, are the following two problems:</p>
  
  <p>1) By structuring my code like this, I must wait for the network response before emitting any data. What I'd like to achieve is to return the flow from room database and show old data, trigger network update and update ui with fresh data. But I needed to structure my code this way because it's the only way i could think about that could tell the UI if the network call failed or not.</p>
  
  <p>2) This code could tecnically only work on it's first execution and if the network call doesn't fail. If i wanted to manually trigger an update, i couldn't because flow only runs when it is first collected (so first execution) or when the room database emits a change (so if the network doesn't fail and i save the result to db).</p>
  
  <p>If you need it, the repo code is this:</p>
  
  <pre><code>val database = Database.getDb()
  val remote = RemoteDataSource()
  fun getInv(): Flow&lt;List&lt;Inv&gt;&gt; = database.invDao().getInv()
  
  suspend fun updateInv(): Exception? {
      return try {
          val inv = remote.getInv()
          database.invDao().saveInvs(inv)
          null
      } catch (e: Exception) {
          e.printStackTrace()
          e
      }
  }
  </code></pre>
  
  <p>Where <code>remote.getInv()</code> is just a retrofit suspend coroutine and database.invDao() is:</p>
  
  <pre><code>@Dao
  interface InvDao {
      @Query("SELECT * FROM Inv")
      fun getInv(): Flow&lt;List&lt;Inv&gt;&gt;
  
      @Insert(onConflict = OnConflictStrategy.REPLACE)
      fun saveInv(inv: Inv)
  
      @Insert(onConflict = OnConflictStrategy.REPLACE)
      fun saveInvs(invs: List&lt;Inv&gt;)
  }
  </code></pre>
  
  <p>I don't need to have all the data in a single flow if it's not the recommended way to do it, i just need to know what is the right way to implement a good repository using room with flow and retrofit coroutine, and having the db as the single source of truth.</p>