You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

移除suspend修饰符触发No virtual method错误的原因解析

问题

我在编写从Room获取数据的代码时,IDE提示suspend是无用修饰符。移除该修饰符后,程序抛出如下错误:

E/AndroidRuntime: FATAL EXCEPTION: DefaultDispatcher-worker-1
    Process: com.example.lightweight, PID: 6483
    java.lang.NoSuchMethodError: No virtual method getWorkoutList(Lkotlin/coroutines/Continuation;)Ljava/lang/Object; in class Lcom/example/lightweight/data/repository/WorkoutListRepository; or its super classes (declaration of 'com.example.lightweight.data.repository.WorkoutListRepository' appears in /data/data/com.example.lightweight/code_cache/.overlay/base.apk/classes13.dex)
        at com.example.lightweight.presentation.viewmodel.WorkoutListViewModel$getList$1.invokeSuspend(WorkoutListViewModel.kt:23)
        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
        at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
        at kotlinx.coroutines.internal.LimitedDispatcher.run(LimitedDispatcher.kt:42)
        at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:95)
        at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:570)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:749)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:677)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:664)
        Suppressed: kotlinx.coroutines.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@6975010, Dispatchers.IO]
I/Process: Sending signal. PID: 6483 SIG: 9

但保留suspend修饰符时程序运行正常,请问这是什么原因?

相关代码

DAO

@Dao
interface WorkoutDao {
    @Query("SELECT * From WorkoutListTest")
    fun getWorkoutList() : List<WorkoutListTest>
}

ViewModel

class WorkoutListViewModel(
    private val repository: WorkoutListRepository
) : ViewModel() {

    private var _list = MutableLiveData<List<String>>()
    val list: LiveData<List<String>>
        get() = _list


    fun getList() {
        viewModelScope.launch(Dispatchers.IO) {
            repository.getWorkoutList()
        }
    }
}

Repository

class WorkoutListRepository(private val dao: WorkoutDao) {
    fun getWorkoutList() : List<WorkoutListTest> {
        val list: List<WorkoutListTest> = dao.getWorkoutList()
        return list
    }
}

Fragment中使用ViewModel的代码

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    vm.getList()
    vm.list.observe(viewLifecycleOwner) { list ->

    }
}
原因分析与解决方案

核心问题:编译缓存不匹配 + Room查询的协程规范

  1. 编译缓存导致方法签名冲突
    之前你给getWorkoutList加过suspend修饰符,编译后这个方法会自动带上Continuation类型的参数(协程底层用来处理回调的参数)。后来你移除了suspend,但IDE的编译缓存没清干净,旧的ViewModel字节码还在调用带Continuation的方法,而新编译的Repository里已经是无参数的普通方法了,直接导致NoSuchMethodError。

  2. IDE提示suspend无用的误区
    现在你的DAO用的是同步查询(fun返回List),Repository的方法只是直接调用DAO,没有挂起逻辑,所以IDE会提示suspend无用。但这其实不符合Room的最佳实践:Room的同步查询会阻塞当前线程,虽然你现在在Dispatchers.IO里调用没问题,但手动管理线程容易出错,Room本身推荐用挂起函数来做数据库操作,它会自动把查询调度到后台线程。

解决步骤

1. 彻底清理编译缓存

先执行IDE的「Clean Project」,再执行「Rebuild Project」,把旧的编译产物全部清掉,确保ViewModel和Repository的方法签名完全对齐。

2. 改用Room推荐的挂起函数查询

把DAO的查询改成挂起函数,这样Room会自动处理线程,代码更安全:

@Dao
interface WorkoutDao {
    @Query("SELECT * From WorkoutListTest")
    suspend fun getWorkoutList() : List<WorkoutListTest>
}

对应更新Repository的方法:

class WorkoutListRepository(private val dao: WorkoutDao) {
    suspend fun getWorkoutList() : List<WorkoutListTest> {
        return dao.getWorkoutList()
    }
}

这样IDE就不会再提示suspend无用,同时也避免了手动线程调度的潜在问题。

3. 补全ViewModel的数据更新逻辑

你当前的ViewModel调用repository.getWorkoutList()后,没有把结果赋值给_list,需要补充这部分代码才能让Fragment观察到数据变化:

fun getList() {
    viewModelScope.launch(Dispatchers.IO) {
        val workoutList = repository.getWorkoutList()
        // 根据你的WorkoutListTest实体类,转换为String列表
        val stringList = workoutList.map { it.yourPropertyName }
        _list.postValue(stringList)
    }
}

内容的提问来源于stack exchange,提问作者ybybyb

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 06:20:29