【问题标题】:Problem with suspend function in Kotlin coroutineKotlin协程中的挂起函数问题
【发布时间】:2020-09-15 05:20:29
【问题描述】:

我正在关注这个视频以使用 Kotlin 协程:https://www.youtube.com/watch?v=BOHK_w09pVA&t=1326s ,在视频中的 9:30。 但是当我编写类似的代码时,它的行为并不像我预期的那样:

WalletDao.kt

interface WalletDao {
    @Query("SELECT * FROM wallet LIMIT 1")
    suspend fun getFirstWallet(): Wallet
}

Repository.kt

class Repository private constructor(appContext: Context) {
    private val appDatabase = AppDatabase.getInstance(appContext)
//current wallet
    private var _currentWallet : MutableLiveData<Wallet> = MutableLiveData()
    var currentWallet : LiveData<Wallet> = _currentWallet
    suspend fun initFirstWallet()
    {
        val fW = withContext(Dispatchers.IO)
        {
            appDatabase.walletDao.getFirstWallet()
        }
        _currentWallet.value = fW
    }
}

MainViewModel.kt

class MainActivityViewModel(private val repository: Repository) : ViewModel()
{
    var currentWallet: LiveData<Wallet> = repository.currentWallet
    init {
        viewModelScope.launch {
            repository.initFirstWallet()
        }
    }
}

MainActivity.kt

class MainActivity : AppCompatActivity() {
    private lateinit var viewModel: MainActivityViewModel
    private fun registerObservers() {
        ...
       
        viewModel.currentWallet.observe(this)
        {
            if (it != null) {
                binding.walletName.text = it.name
                binding.walletBalance.text = it.amount.toString()
                viewModel.onCurrentWalletChange()
            }
        }
    }
}

当我在 MainActivity 中运行代码时,有时会调用 viewModel.currentWallet 的 lambda,并且会显示当前钱包的名称,大多数时候它不会被调用。 我已将代码更改为以下但没有改变:

Repository.kt

class Repository private constructor(appContext: Context) {
    suspend fun initFirstWallet()
    {
        withContext(Dispatchers.IO)
        {
            _currentWallet.postValue(appDatabase.walletDao.getFirstWallet())
        }
    }
}

你能告诉我上面的代码有什么问题吗???非常感谢!

【问题讨论】:

  • 您不必在存储库中使用withContext(Dispatchers.IO) 我认为Room 会为您处理它。删除并尝试使用 _currentWallet.postValue(appDatabase.walletDao.getFirstWallet())

标签: android kotlin android-room kotlin-coroutines


【解决方案1】:

你不需要为此使用协程。

WalletDao.kt

interface WalletDao {
    @Query("SELECT * FROM wallet LIMIT 1")
    fun getFirstWallet(): LiveData<Wallet>
}

Repository.kt

class Repository private constructor(appContext: Context) {
    private val appDatabase = AppDatabase.getInstance(appContext)

    fun initFirstWallet() = appDatabase.walletDao.getFirstWallet()
}

MainActivityViewModel.kt

class MainActivityViewModel(private val repository: Repository) : ViewModel()
{
    var currentWallet: LiveData<Wallet> = repository.initFirstWallet()
    
}

这将按预期正常工作,没有任何线程问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-05-31
    • 1970-01-01
    • 2019-10-20
    • 2021-10-02
    • 2019-05-30
    • 2018-01-10
    • 2021-01-04
    • 2019-10-10
    相关资源
    最近更新 更多