在 ViewModel 中使用 viewModelScope.launch 调用暂停方法时出现 "No virtual method getTag(Ljava/lang/String;)" 错误
Getting "No virtual method getTag(Ljava/lang/String;)" error when calling suspended method using viewModelScope.launch inside ViewModel
我正在尝试通过 viewModelScope.launch()
调用挂起的方法,但应用程序在调用该方法后立即崩溃。
我应该指出,我使用的是最新版本的 androidX 稳定库。
然而,对于 ViewModel 和 LiveData,我使用的是 2.2.0-alpha02
的 alpha 版本。
当然,Retrofit 版本是 2.6.0
,所以将它的功能标记为暂停应该没问题。
此外,变量是使用 Koin 初始化的。
日志:
java.lang.NoSuchMethodError: No virtual method getTag(Ljava/lang/String;)Ljava/lang/Object; in class Landroidx/lifecycle/ViewModel; or its super classes (declaration of 'androidx.lifecycle.ViewModel' appears in /data/app/co.nilin.varabank-lUNWj0JGUm_fCoYkMmbbJg==/base.apk)
at androidx.lifecycle.ViewModelKt.getViewModelScope(ViewModel.kt:36)
at co.nilin.varabank.home.HomeViewModel.fetchRates(HomeViewModel.kt:18)
at co.nilin.varabank.home.HomeActivity$init.onClick(HomeActivity.kt:27)
at android.view.View.performClick(View.java:6597)
at android.view.View.performClickInternal(View.java:6574)
at android.view.View.access00(View.java:778)
at android.view.View$PerformClick.run(View.java:25885)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
改造网络服务:
interface BankCalculatorWebService {
@GET("auto/bank-gateway/general/{bank}/currencies")
suspend fun fetchCurrencyRates(@Path("bank") bank: String): Response<CurrencyRateResponse>
}
存储库:
class BankCalculatorRepositoryImpl(
private val webService: BankCalculatorWebService
) : BankCalculatorRepository {
override suspend fun fetchRates(): List<CurrencyRateDTO> {
val list = ArrayList<CurrencyRateDTO>()
val response = webService.fetchCurrencyRates(Bank.getDefaultBank().swiftCode)
response.ifSuccessful { response ->
response.items.forEach {
list.add(CurrencyRateDTO.fromCurrencyRate(it))
}
}
return list
}
}
查看模型:
class HomeViewModel(
private val repository: BankCalculatorRepository
) : ViewModel() {
val rates = MutableLiveData<List<CurrencyRateDTO>>()
fun fetchRates() {
viewModelScope.launch {
val response = repository.fetchRates()
rates.postValue(response)
}
}
}
里面的代码activity
viewModel.rates.observe(this) {
Toast.makeText(this, it.size, Toast.LENGTH_SHORT).show()
}
button.setOnClickListener {
viewModel.fetchRates()
}
我也遇到了同样的问题。除了自己实现 viewModelScope 之外,我找不到任何解决方案。您的 HomeViewModel 代码将如下所示
class HomeViewModel(
private val repository: BankCalculatorRepository
) : ViewModel() {
private val viewModelJob = SupervisorJob()
protected val uiScope = CoroutineScope(Dispatchers.Main + viewModelJob)
val rates = MutableLiveData<List<CurrencyRateDTO>>()
fun fetchRates() {
uiScope.launch {
val response = repository.fetchRates()
rates.postValue(response)
}
}
/**
* Cancel all coroutines when the ViewModel is cleared
*/
override fun onCleared() {
super.onCleared()
uiScope.coroutineContext.cancelChildren()
}
}
这是由于对 androidx.lifecycle.ViewModel
class 不同版本的依赖污染了您的 class 路径(可能是 2.2.0 和 2.0.0 版本)。这通常是由于来自过时库的传递依赖。对我来说,是 support-v4 库导致的。
运行 ./gradlew app:dependencies
查看您的树,然后查找 ViewModel
上的传递依赖项。对于那些正在引入旧版本的库,要么更新它们,要么为它们排除 ViewModel
依赖项:
implemenation ("com.<library>") {
exclude group:'androidx.lifecycle', module:'lifecycle-viewmodel'
}
我正在尝试通过 viewModelScope.launch()
调用挂起的方法,但应用程序在调用该方法后立即崩溃。
我应该指出,我使用的是最新版本的 androidX 稳定库。
然而,对于 ViewModel 和 LiveData,我使用的是 2.2.0-alpha02
的 alpha 版本。
当然,Retrofit 版本是 2.6.0
,所以将它的功能标记为暂停应该没问题。
此外,变量是使用 Koin 初始化的。
日志:
java.lang.NoSuchMethodError: No virtual method getTag(Ljava/lang/String;)Ljava/lang/Object; in class Landroidx/lifecycle/ViewModel; or its super classes (declaration of 'androidx.lifecycle.ViewModel' appears in /data/app/co.nilin.varabank-lUNWj0JGUm_fCoYkMmbbJg==/base.apk)
at androidx.lifecycle.ViewModelKt.getViewModelScope(ViewModel.kt:36)
at co.nilin.varabank.home.HomeViewModel.fetchRates(HomeViewModel.kt:18)
at co.nilin.varabank.home.HomeActivity$init.onClick(HomeActivity.kt:27)
at android.view.View.performClick(View.java:6597)
at android.view.View.performClickInternal(View.java:6574)
at android.view.View.access00(View.java:778)
at android.view.View$PerformClick.run(View.java:25885)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
改造网络服务:
interface BankCalculatorWebService {
@GET("auto/bank-gateway/general/{bank}/currencies")
suspend fun fetchCurrencyRates(@Path("bank") bank: String): Response<CurrencyRateResponse>
}
存储库:
class BankCalculatorRepositoryImpl(
private val webService: BankCalculatorWebService
) : BankCalculatorRepository {
override suspend fun fetchRates(): List<CurrencyRateDTO> {
val list = ArrayList<CurrencyRateDTO>()
val response = webService.fetchCurrencyRates(Bank.getDefaultBank().swiftCode)
response.ifSuccessful { response ->
response.items.forEach {
list.add(CurrencyRateDTO.fromCurrencyRate(it))
}
}
return list
}
}
查看模型:
class HomeViewModel(
private val repository: BankCalculatorRepository
) : ViewModel() {
val rates = MutableLiveData<List<CurrencyRateDTO>>()
fun fetchRates() {
viewModelScope.launch {
val response = repository.fetchRates()
rates.postValue(response)
}
}
}
里面的代码activity
viewModel.rates.observe(this) {
Toast.makeText(this, it.size, Toast.LENGTH_SHORT).show()
}
button.setOnClickListener {
viewModel.fetchRates()
}
我也遇到了同样的问题。除了自己实现 viewModelScope 之外,我找不到任何解决方案。您的 HomeViewModel 代码将如下所示
class HomeViewModel(
private val repository: BankCalculatorRepository
) : ViewModel() {
private val viewModelJob = SupervisorJob()
protected val uiScope = CoroutineScope(Dispatchers.Main + viewModelJob)
val rates = MutableLiveData<List<CurrencyRateDTO>>()
fun fetchRates() {
uiScope.launch {
val response = repository.fetchRates()
rates.postValue(response)
}
}
/**
* Cancel all coroutines when the ViewModel is cleared
*/
override fun onCleared() {
super.onCleared()
uiScope.coroutineContext.cancelChildren()
}
}
这是由于对 androidx.lifecycle.ViewModel
class 不同版本的依赖污染了您的 class 路径(可能是 2.2.0 和 2.0.0 版本)。这通常是由于来自过时库的传递依赖。对我来说,是 support-v4 库导致的。
运行 ./gradlew app:dependencies
查看您的树,然后查找 ViewModel
上的传递依赖项。对于那些正在引入旧版本的库,要么更新它们,要么为它们排除 ViewModel
依赖项:
implemenation ("com.<library>") {
exclude group:'androidx.lifecycle', module:'lifecycle-viewmodel'
}