title: Make part of coroutine continue past cancellation
body: <p>I have a file managing class that can save a big file. The file manager class is an application singleton, so it outlives my UI classes. My Activity/Fragment can call the <code>save</code> suspend function of the file manager from a coroutine and then show success or failure in the UI. For example:</p>
  
  <pre><code>//In MyActivity:
  private fun saveTheFile() = lifecycleScope.launch {
      try {
          myFileManager.saveBigFile()
          myTextView.text = "Successfully saved file"
      } catch (e: IOException) {
          myTextView.text = "Failed to save file"
      }
  }
  
  //In MyFileManager
  suspend fun saveBigFile() {
      //Set up the parameters
      //...
  
      withContext(Dispatchers.IO) {
          //Save the file
          //...
      }
  }
  </code></pre>
  
  <p>The problem with this approach is that I don't want the save operation to be aborted if the Activity is finished. If the activity is destroyed before the <code>withContext</code> block gets going, or if the <code>withContext</code> block has any suspension points in it, then saving will not be completed because the coroutine will be canceled.</p>
  
  <p>What I want to happen is that the file is always saved. If the Activity is still around, then we can show UI updates on completion.</p>
  
  <p>I thought one way to do it might be to start a new <code>coroutineScope</code> from the suspend function like this, but this scope still seems to get cancelled when its parent job is cancelled.</p>
  
  <pre><code>suspend fun saveBigFile() = coroutineScope {
      //...
  }
  </code></pre>
  
  <p>I thought another alternative might be to make this a regular function that updates some LiveData when it's finished. The Activity could observe the live data for the result, and since LiveData automatically removes lifecycle observers when they're destroyed, the Activity is not leaked to the FileManager. I'd like to avoid this pattern if the something less convoluted like the above can be done instead.</p>
  
  <pre><code>//In MyActivity:
  private fun saveTheFile() {
      val result = myFileManager.saveBigFile()
      result.observe(this@MyActivity) {
          myTextView.text = when (it) {
              true -&gt; "Successfully saved file"
              else -&gt; "Failed to save file"
          }
      }
  }
  
  //In MyFileManager
  fun saveBigFile(): LiveData&lt;Boolean&gt; {
      //Set up the parameters
      //...
      val liveData = MutableLiveData&lt;Boolean&gt;()
      MainScope().launch {
          val success = withContext(Dispatchers.IO) {
              //Save the file
              //...
          }
          liveData.value = success
      }
      return liveData
  }
  </code></pre>