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

Retrofit2调用在viewModelScope中失败但在lifecycleScope中正常的问题求助

Retrofit2调用在viewModelScope中失败但在lifecycleScope中正常的问题求助

大家好,我正在做一个大学项目,开发一款模拟超市电商的Android应用。我用Retrofit2和Moshi对接产品数据库的REST API,所有业务逻辑都放在ViewModel里处理,但现在碰到了一个诡异的问题:

当我在viewModelScope.launch{ ... }代码块里发送GET请求时,Retrofit好像完全没有返回任何内容;可把一模一样的代码移到MainActivity里,用lifecycleScope.launch{ ... }运行就完全正常。

下面是我的相关代码:

ProductService接口

interface ProductService {
    @GET("product")
    suspend fun getAllProducts(): Response<List<Product>>

    @GET("product/{pId}")
    suspend fun getProductById(@Path("pId") pId: Int): Response<Product>

    @POST("product")
    suspend fun createNewProduct(@Body post: POST): POST
}

Retrofit与Moshi配置的单例WPAPI

object WPAPI {
    val moshi: Moshi = Moshi.Builder()
        .add(com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory())
        .build()

    val logging = HttpLoggingInterceptor().apply {
        level = HttpLoggingInterceptor.Level.BODY
    }

    val client = OkHttpClient.Builder()
        .addInterceptor(logging)
        .build()

    val retrofitService : ProductService by lazy {
        Retrofit.Builder()
            .baseUrl("http://[redacted]:8080/api/")
            .addConverterFactory(MoshiConverterFactory.create(moshi))
            .client(client)
            .build()
            .create(ProductService::class.java)
    }
}

ProductViewModel中的getAllProducts方法

fun getAllProducts() : LiveData<List<Product>> {
    val result = MutableLiveData<List<Product>>()
    viewModelScope.launch {
        val response: Response<List<Product>> = try {
            WPAPI.retrofitService.getAllProducts()
        } catch (e: IOException) {
            Log.e("ProductViewModel", "IOException", e)
            return@launch
        } catch (e: HttpException) {
            Log.e("ProductViewModel", "HttpException", e)
            return@launch
        } catch (e: Exception) {
            Log.wtf("ProductViewModel", "Exception", e)
            return@launch
        }

        if (response.isSuccessful && response.body() != null) {
            Log.i("ProductViewModel", "Response is good")
            result.postValue(response.body()!!)
        }
    }
    return result
}

在MainActivity中调用ViewModel方法的方式

val productsDBList : List<Product> = viewModel.getAllProducts().value!!

我用调试器一步步走代码的时候,在ViewModel里刚执行到WPAPI.retrofitService.getAllProducts()这一行,就直接跳到了方法末尾的return result,整个过程LogCat里没有任何错误日志输出,最后因为上面代码里的!!运算符抛出了NullPointerException。

我本来怀疑是ViewModel的onCleared()方法被提前调用了,但重写这个方法后发现根本没触发。

对比之下,在MainActivity里用lifecycleScope的代码就完全正常:

lifecycleScope.launch {
    val response: Response<List<Product>> = try {
        WPAPI.retrofitService.getAllProducts()
    } catch (e: IOException) {
        Log.e("ProductViewModel", "IOException", e)
        return@launch
    } catch (e: HttpException) {
        Log.e("ProductViewModel", "HttpException", e)
        return@launch
    } catch (e: Exception) {
        Log.wtf("ProductViewModel", "Exception", e)
        return@launch
    }

    if (response.isSuccessful && response.body() != null) {
        Log.i("LifecycleScope", "Response is good")
        val pAdapter = ProductAdapter(response.body()!!)
        productsRecView.adapter = pAdapter
        productsRecView.layoutManager= LinearLayoutManager(this@MainActivity)
    }
}

我感觉自己肯定漏了某个很基础的点,有没有大佬能帮我指个方向?

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.08 09:18:06