Kotlin Android项目调用await()报未解析引用错误如何解决?
错误原因
你调用await()的对象是bookViewModel.getBookList()的返回值,这个方法的返回类型是BookList?,不是Deferred/Retrofit Call这类需要等待执行的异步对象,自然不存在await()方法,所以会报未解析引用错误。
解决方案
1 快速修复当前错误
直接把await()删除即可,你的getBookList()本身就是suspend挂起函数,在协程内直接调用就会自动挂起等待结果,不需要额外加await:
GlobalScope.launch(Dispatchers.IO) { bookList = bookViewModel.getBookList() }
但当前写法存在内存泄漏、数据更新后Compose无法自动刷新UI的问题,更推荐用下面的响应式改造方案。
2 适配Compose的最优实现方案
步骤1:改造ViewModel,用可观察容器持有数据
@HiltViewModel class BookViewModel @Inject constructor( private val repository: BookRepository ) : ViewModel() { // 用StateFlow持有列表数据,支持响应式更新 private val _bookList = MutableStateFlow<BookList?>(null) val bookList = _bookList.asStateFlow() fun fetchBookList() { // 用viewModelScope启动协程,ViewModel销毁时自动取消协程,避免内存泄漏 viewModelScope.launch { _bookList.value = repository.getBookList() } } }
步骤2:改造Repository,添加异常捕获
suspend fun getBookList() : BookList? { return try { val response = retrofitApi.getBookList() if (response.isSuccessful) response.body() else null } catch (e: Exception) { e.printStackTrace() null } }
步骤3:改造Activity,在Compose中响应数据渲染UI
@AndroidEntryPoint class MainActivity : ComponentActivity() { private val bookViewModel: BookViewModel by viewModels() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // 进入页面触发数据拉取 bookViewModel.fetchBookList() setContent { LOTRAppTheme { // 收集StateFlow数据,页面在前台时才会响应更新,更省电 val bookList by bookViewModel.bookList.collectAsStateWithLifecycle() when { bookList == null -> { // 加载中状态UI Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { CircularProgressIndicator() } } else -> { // 渲染书籍列表 LazyColumn(modifier = Modifier.fillMaxSize()) { items(bookList!!.books) { book -> Text( text = book.name, modifier = Modifier.padding(16.dp) ) } } } } } } } }
可选依赖补充
如果使用collectAsStateWithLifecycle需要添加以下依赖:
implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.6.2"
不想加依赖可以替换为collectAsState(initial = null),功能一致,仅缺少生命周期优化。
内容的提问来源于stack exchange,提问作者Hasan Altay
相关产品推荐
相关产品推荐

