如何使用ViewModel从Repository获取API数据及现有代码正确性排查
代码问题修正
1. AppModule 问题修复
现有代码中providesPokemonRepository方法命名和返回的MovieRepository类型不匹配,属于命名规范问题,修正后代码如下:
@Module @InstallIn(SingletonComponent::class) object AppModule { @Provides @Singleton // 修正方法命名,和返回的MovieRepository保持一致 fun providesMovieRepository( api: MovieApiService ) = MovieRepository(api) @Singleton @Provides fun providesMovieApi(): MovieApiService { return Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .build() .create(MovieApiService::class.java) } }
Repository代码本身没有逻辑问题,可以正常使用。
2. ViewModel 问题修复
现有代码存在两个核心问题:
errorMessage用val声明,配合by mutableStateOf时无法修改值,需要改为vargetMovies方法拿到请求结果后没有做状态分发,也没有处理加载、成功、失败的状态流转
修正后代码如下:
@HiltViewModel class MovieViewModel @Inject constructor(private val repository: MovieRepository) : ViewModel() { // 用by mutableStateOf的变量需要声明为var才能修改值 var response: List<MoviesItem> by mutableStateOf(listOf()) var errorMessage: String by mutableStateOf("") var isLoading by mutableStateOf(false) fun getMovies() = viewModelScope.launch { isLoading = true when(val result = repository.getMovieLists()) { is Resource.Success -> { response = result.data errorMessage = "" } is Resource.Error -> { errorMessage = result.message ?: "未知错误" response = emptyList() } } isLoading = false } }
请确保你的Resource密封类定义符合通用规范,参考示例:
sealed class Resource<out T> { data class Success<out T>(val data: T) : Resource<T>() data class Error(val message: String?) : Resource<Nothing>() }
调用示例
以Compose页面为例,调用方式如下:
@Composable fun MovieScreen(viewModel: MovieViewModel = hiltViewModel()) { LaunchedEffect(Unit) { viewModel.getMovies() } when { viewModel.isLoading -> { // 渲染加载中UI } viewModel.errorMessage.isNotEmpty() -> { // 渲染错误提示UI } else -> { // 用viewModel.response渲染电影列表 } } }
学习建议
- 你遇到的问题属于Jetpack组件组合使用的熟练度问题,不是基础编码能力不足,不需要自我怀疑。这类分层架构的写法有固定套路,完成2-3个完整的小demo即可熟练掌握。
- 可以拆分模块逐个突破:先单独搞懂Hilt依赖注入的规则,再练熟Repository+协程的网络请求封装,最后搞清楚ViewModel和UI状态的绑定逻辑,不要一开始就把所有组件堆在一起写,容易混乱。
- 写完功能后可以对照官方文档核对每个组件的写法规范,比如依赖注入的命名、State的正确声明方式、viewModelScope的生命周期这些细节,多注意几次就能避免低级错误。
内容的提问来源于stack exchange,提问作者Arfin Hosain
相关产品推荐
相关产品推荐

