title: Android Coroutines block UI click listener
body: <p>I'm using MVVM as architecture, also the repository pattern. I have a Web service, a room database also. Using coroutines block any button I click.</p>
  
  <p>There's a list/detail implemented with a fragment and an activity respectively.</p>
  
  <p>I can figure out what's wrong in the way I implemented the coroutines and Viewmodel.</p>
  
  <pre><code>class BuySharedViewModel(application: Application) : AndroidViewModel(application) {
  private val repository: BuyRepository
  var allBuys: LiveData&lt;List&lt;Buy&gt;&gt;
  
  
  init {
      val buyDao = KunukRoomDatabase.getDatabase(application, viewModelScope).buyDao()
      val buyRemote = BuyRemote()
      repository = BuyRepository.getInstance(buyDao , buyRemote)
      //Use async because it return a result
      viewModelScope.launch { getAllBuys() }
      allBuys = buyDao.loadAllBuys()
  }
  
  private suspend fun getAllBuys() {
      repository.getBuys()
  
  }
  }
  </code></pre>
  
  <p>Here's is the Repository, it take data from web service and add it to the room database, while ViewModel get's data from room database.</p>
  
  <pre><code>class BuyRepository (private val buyDao: BuyDao, private val buyRemote: BuyRemote) {
  private val job = SupervisorJob()
  private val scope = CoroutineScope(Dispatchers.Default + job)
  
  companion object {
      //For singleton instantiation
      @Volatile private var instance: BuyRepository? = null
  
      fun getInstance(buyDao: BuyDao, buyRemote: BuyRemote) =
          instance ?: synchronized(this) {
              instance ?: BuyRepository(buyDao, buyRemote)
                  .also { instance = it}
  
          }
  }
  
  
  suspend fun getBuys(){
      refresh()
  }
  
  private suspend fun refresh(){
  
      try {
          val list = scope.async { buyRemote.loadBuys() }
          list.await().forEach { buy -&gt; insert(buy) }
      } catch (e: Throwable) {}
  }
  
  
  @WorkerThread
  private fun insert(buy: Buy) {
      buyDao.insertBuy(buy)
  }
  
  
  }
  </code></pre>
  
  <p>The fragment work, data are displayed, when i click on an item from that fragment(recyclerView) it work, the activity display details data. But none of the click on that activity works, like it doesn't detect the clicks. I guess it got something to do with the coroutines because when I comment out the code <code>viewmodelScope.launch { getAllBuys()}</code> from the BuySharedViewModel it works, because it load data from the previous call from room database, and the clicks works. </p>
  
  <p>Here's the code in the detail view:</p>
  
  <pre><code>class BuyDetailActivity : AppCompatActivity() {
  private lateinit var sharedViewModel: BuySharedViewModel
  
  override fun onCreate(savedInstanceState: Bundle?) {
      super.onCreate(savedInstanceState)
      lateinit var buy: Buy
  
      sharedViewModel = ViewModelProviders.of(this).get(BuySharedViewModel::class.java)
  
      val position = intent.getIntExtra("position", 0)
      sharedViewModel.allBuys.observe(this, Observer&lt;List&lt;Buy&gt;&gt; { buys -&gt;
          buy = buys[position]
          val binding: com.example.drake.kunuk.databinding.ActivityBuyDetailBinding =
              DataBindingUtil.setContentView(this, com.example.drake.kunuk.R.layout.activity_buy_detail)
          binding.buy = buy
  
  
          val agentNumber = buy.agentNumber?:"+50937438713"
          bnvContactAgent.setOnNavigationItemSelectedListener { item -&gt;
  
              when (item.itemId) {
                  com.example.drake.kunuk.R.id.action_call -&gt; {
                      val callNumberUri = Uri.parse("tel:$agentNumber")
                      val callIntent = Intent(Intent.ACTION_DIAL, callNumberUri)
                      startActivity(callIntent)
                  }
                  com.example.drake.kunuk.R.id.action_sms -&gt; {
                      val smsNumberUri = Uri.parse("sms:$agentNumber")
                      val smsIntent = Intent(Intent.ACTION_SENDTO, smsNumberUri)
                      startActivity(smsIntent)
                  }
                  com.example.drake.kunuk.R.id.action_email -&gt; {
                      val uriText = "mailto:drakecolin@gmail.com" +
                              "?subject=" + Uri.encode("I'm interested in $agentNumber") +
                              "&amp;body=" + Uri.encode("Hello, ")
  
                      val uri = Uri.parse(uriText)
  
                      val sendIntent = Intent(Intent.ACTION_SENDTO)
                      sendIntent.data = uri
                      startActivity(Intent.createChooser(sendIntent, "Send email"))
                  }
              }
              false
          }
  </code></pre>
  
  <p>This is the code of my fragment:</p>
  
  <pre><code>class BuyFragment : Fragment() {
  companion object {
      fun newInstance() = BuyFragment()
  }
  
  private lateinit var viewModel: BuySharedViewModel
  private val buyList = ArrayList&lt;Buy&gt;()
  
  override fun onCreate(savedInstanceState: Bundle?) {
      super.onCreate(savedInstanceState)
      // Get a new or existing ViewModel from the ViewModelProvider.
      viewModel = ViewModelProviders.of(this).get(BuySharedViewModel::class.java)
  
      // Add an observer on the LiveData returned by loadAllBuys.
      // The onChanged() method fires when the observed data changes and the activity is
      // in the foreground.
      viewModel.allBuys.observe(this, Observer&lt;List&lt;Buy&gt;&gt; { buys -&gt;
          // Update the cached copy of the words in the adapter.
          buys?.let { (rvBuy.adapter as BuyAdapter).setBuys(it) }
          progressBar.visibility = View.GONE
      })
  }
  
  override fun onCreateView(
      inflater: LayoutInflater, container: ViewGroup?,
      savedInstanceState: Bundle?
  ): View? {
      return inflater.inflate(R.layout.buy_fragment, container, false)
  }
  
  override fun onActivityCreated(savedInstanceState: Bundle?) {
      super.onActivityCreated(savedInstanceState)
      rvBuy.layoutManager = LinearLayoutManager(context)
      rvBuy.adapter = BuyAdapter(activity!!.applicationContext,
          R.layout.buy_card, buyList)
      progressBar.visibility = View.VISIBLE
  
  
  }
  }
  </code></pre>
  
  <p>This is the code for the BuyDao:</p>
  
  <pre><code>@Dao
  </code></pre>
  
  <p>interface BuyDao {
      @Insert(onConflict = OnConflictStrategy.REPLACE)
      fun insertBuy(vararg buys: Buy)</p>
  
  <pre><code>@Update
  fun updateBuy(vararg buys: Buy)
  
  @Delete
   fun deleteBuys(vararg buys: Buy)
  
  @Query("SELECT * FROM buys")
  fun loadAllBuys(): LiveData&lt;List&lt;Buy&gt;&gt;
  
  @Query("DELETE FROM buys")
  suspend fun deleteAll()
  
  }
  </code></pre>