如何在使用协程的ViewModel中正确实现Result.Success与Result.Error
改造步骤
1. 改造 GiphyTaskRepository 层
首先在仓库层对请求结果和异常做统一包装,直接返回你定义的Result密封类:
class GiphyTaskRepository @Inject constructor(private val giphyTaskApiService: GiphyTaskApiService) { suspend fun getGifsFromText(apikey:String,text:String,limit:Int): Result { return try { val response = giphyTaskApiService.getGifsFromText(apikey,text,limit) when { // 请求成功且响应体不为空 response.isSuccessful && response.body() != null -> { Result.Success(response.body()!!.data) } // 请求成功但响应体为空/请求失败 else -> { Result.Error(Exception(response.message() ?: "请求失败,响应内容为空")) } } } catch (e: Exception) { // 捕获网络异常、超时、序列化失败等请求过程中抛出的异常 Result.Error(e) } } }
2. 改造 GiphyTaskViewModel 层
调整LiveData的类型为Result,直接接收仓库返回的密封类结果:
@HiltViewModel class GiphyTaskViewModel @Inject constructor(private val giphyTaskRepository: GiphyTaskRepository):ViewModel() { // 调整LiveData类型为Result,包含成功/失败两种状态 var giphyresponse = MutableLiveData<Result>() fun getGifsFromText(apikey:String,text:String,limit:Int)= viewModelScope.launch { val result = giphyTaskRepository.getGifsFromText(apikey,text,limit) giphyresponse.postValue(result) } }
3. 页面层使用示例
在Activity/Fragment观察LiveData时,直接判断密封类类型即可处理对应逻辑:
viewModel.giphyresponse.observe(this) { result -> when(result) { is Result.Success -> { val data = result.data as List<DataItem> // 渲染列表逻辑 } is Result.Error -> { val errorMsg = result.exception.message ?: "未知错误" // 弹窗/toast提示错误逻辑 } } }
可选优化:给Result加上泛型支持
你当前定义的Result携带的成功数据是Any类型,使用时需要强转,建议改成泛型实现提升类型安全性:
// 泛型版Result密封类 sealed class Result<out T> { data class Success<out T>(val data: T) : Result<T>() data class Error(val exception: Exception) : Result<Nothing>() }
对应调整仓库层返回值类型:
suspend fun getGifsFromText(apikey:String,text:String,limit:Int): Result<List<DataItem>> { // 内部逻辑不变,返回时Success携带List<DataItem>即可 }
对应调整ViewModel的LiveData类型:
var giphyresponse = MutableLiveData<Result<List<DataItem>>>()
此时页面层使用时不需要再强转数据类型:
is Result.Success -> { val data = result.data // 自动识别为List<DataItem> }
内容的提问来源于stack exchange,提问作者user16305099
相关产品推荐
相关产品推荐

