简体   繁体   中英

How to perform time-consuming operations in the background and update the UI using coroutines in Kotlin for Android development in Jetpack Compose

I'm developing an android app that is a bitcoin wallet using Jetpack Compose.

I have Wallet.kt file with:

fun sync() {
    Log.i(TAG, "Wallet is syncing")
    wallet.sync(blockchain, LogProgress)
}

fun getBalance(): ULong = wallet.getBalance().total

then in HomeScreen.kt I have

internal class WalletViewModel() : ViewModel() {
  private var _balance: MutableLiveData<ULong> = MutableLiveData(0u)
  val balance: LiveData<ULong>
      get() = _balance

  fun updateBalance() {
    Wallet.sync()
    _balance.value = Wallet.getBalance()
  }

then outside of this is composable function HomeScreen

internal fun HomeScreen(
  navController: NavController,
  walletViewModel: WalletViewModel = viewModel()
) {
   val balance by walletViewModel.balance.observeAsState()
   Image(Modifier.clickable{ walletViewModel.updateBalance() }
}

My problem being that when I click on that Image which has clickable, the whole app freezes, until the updateBalance() is completed. I learned that this is because the sync() function inside Wallet.kt file is performing.network task on the Main Thread and the app is in Main Thread, so the whole app has to wait until sync is done.

Can you suggest how should I implement coroutines or different way, so that the sync happens inside background thread and then updates _balance to/in the Main?

I've tried lots of things, including suspend before sync() and async in the viewModelScope, but nothing seems to work how I want to.

Thanks

You can solve it in two ways, one is to attach the async call into the viewModelScope and mark the async call as suspend, the other one is creating a coroutine in your repository with Context and execute it in another thread.

Solution 1

fun updateBalance() {
  viewModelScope.launch {
    Wallet.sync()
    _balance.value = Wallet.getBalance()
   }
  }

suspend fun sync() {
    Log.i(TAG, "Wallet is syncing")
    wallet.sync(blockchain, LogProgress)
}

Solution 2

suspend fun sync() {
    Log.i(TAG, "Wallet is syncing")
    withContext(Dispatcher.IO) {
      wallet.sync(blockchain, LogProgress)
   }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM