Android Kotlin Retrofit2 不从 Web 服务器返回数据:“无法为 ApiService get 方法创建转换器”

问题描述 投票:0回答:1

我的应用程序在打开时崩溃并显示以下消息:

java.lang.IllegalArgumentException: Unable to create converter for java.util.List<com.dov4k1n.vkinternshiptask.network.Products>
    for method ProductsApiService.getProductsList
 at retrofit2.Utils.methodError(Utils.java:54)
 at retrofit2.HttpServiceMethod.createResponseConverter(HttpServiceMethod.java:126)
 at retrofit2.HttpServiceMethod.parseAnnotations(HttpServiceMethod.java:85)
 at retrofit2.ServiceMethod.parseAnnotations(ServiceMethod.java:39)
 at retrofit2.Retrofit.loadServiceMethod(Retrofit.java:202)
 at retrofit2.Retrofit$1.invoke(Retrofit.java:160)
 at java.lang.reflect.Proxy.invoke(Proxy.java:1006)
 at $Proxy2.getProductsList(Unknown Source)
 at ...

我想使用 Kotlin 和 Android Studio 通过 Retrofit2 库从 Web 服务器 https://dummyjson.com/products 检索产品信息。

这是我的json:

{
    "products": [
        {
            "id": 1,
            "title": "iPhone 9",
            "description": "An apple mobile which is nothing like apple",
            "price": 549,
            "discountPercentage": 12.96,
            "rating": 4.69,
            "stock": 94,
            "brand": "Apple",
            "category": "smartphones",
            "thumbnail": "https://cdn.dummyjson.com/product-images/1/thumbnail.jpg",
            "images": [
                "https://cdn.dummyjson.com/product-images/1/1.jpg",
                "https://cdn.dummyjson.com/product-images/1/2.jpg",
                "https://cdn.dummyjson.com/product-images/1/3.jpg",
                "https://cdn.dummyjson.com/product-images/1/4.jpg",
                "https://cdn.dummyjson.com/product-images/1/thumbnail.jpg"
            ]
        },
        {
            "id": 2,
            "title": "iPhone X",
            "description": "SIM-Free, Model A19211 6.5-inch Super Retina HD display with OLED technology A12 Bionic chip with ...",
            "price": 899,
            "discountPercentage": 17.94,
            "rating": 4.44,
            "stock": 34,
            "brand": "Apple",
            "category": "smartphones",
            "thumbnail": "https://cdn.dummyjson.com/product-images/2/thumbnail.jpg",
            "images": [
                "https://cdn.dummyjson.com/product-images/2/1.jpg",
                "https://cdn.dummyjson.com/product-images/2/2.jpg",
                "https://cdn.dummyjson.com/product-images/2/3.jpg",
                "https://cdn.dummyjson.com/product-images/2/thumbnail.jpg"
            ]
        },
        {
            "id": 3,
            "title": "Samsung Universe 9",
            "description": "Samsung's new variant which goes beyond Galaxy to the Universe",
            "price": 1249,
            "discountPercentage": 15.46,
            "rating": 4.09,
            "stock": 36,
            "brand": "Samsung",
            "category": "smartphones",
            "thumbnail": "https://cdn.dummyjson.com/product-images/3/thumbnail.jpg",
            "images": [
                "https://cdn.dummyjson.com/product-images/3/1.jpg"
            ]
        }
    ],
    "total": 100,
    "skip": 0,
    "limit": 30
}

这是我的产品数据类:

data class Products(
    val id: Int,
    val title: String,
    val description: String,
    val price: Double,
    val discountPercentage: Double,
    val rating: Double,
    val stock: Int,
    val brand: String,
    val category: String,
    val thumbnail: String,
    val images: List<String>
)

这是我的 ProductsApiService:

import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
import kotlinx.serialization.json.Json
import okhttp3.MediaType.Companion.toMediaType
import retrofit2.Retrofit
import retrofit2.http.GET

private const val BASE_URL = "https://dummyjson.com"
private val retrofit = Retrofit.Builder()
    .addConverterFactory(Json.asConverterFactory("application/json".toMediaType()))
    .baseUrl(BASE_URL)
    .build()

interface ProductsApiService {
    @GET("/products")
    suspend fun getProductsList(): List<Products>
}

object ProductsApi {
    val retrofitService : ProductsApiService by lazy {
        retrofit.create(ProductsApiService::class.java)
    }
}

好像

getProductsList()
功能没有按预期工作

这是我的 ProductsViewModel,我在其中使用此 api 服务,如果有帮助的话:

import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.dov4k1n.vkinternshiptask.network.ProductsApi
import kotlinx.coroutines.launch
import java.io.IOException

sealed interface ProductsUiState {
    data class Success(val products: String) : ProductsUiState
    object Error: ProductsUiState
    object Loading: ProductsUiState
}

class ProductsViewModel : ViewModel() {
    var productsUiState: ProductsUiState by mutableStateOf(ProductsUiState.Loading)
        private set

    init {
        getProducts()
    }

    fun getProducts() {
        viewModelScope.launch {
            productsUiState = try {
                val listResult = ProductsApi.retrofitService.getProductsList()
                ProductsUiState.Success(
                    "Success: ${listResult.size} products retrieved"
                )
            }
            catch (e: IOException) {
                ProductsUiState.Error
            }
        }
    }
}

我在依赖项中使用它:

// Retrofit
    implementation("com.squareup.retrofit2:retrofit:2.9.0")
    // Retrofit with Kotlin serialization Converter
    implementation("com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:1.0.0")
    implementation("com.squareup.okhttp3:okhttp:4.11.0")
    // Kotlin serialization
    implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.3")

还有这个插件:

id("org.jetbrains.kotlin.plugin.serialization") version "1.9.22"

我几乎按照 Google 的 Codelab 进行了所有操作 https://developer.android.com/codelabs/basic-android-kotlin-compose-getting-data-internet

但是在Codelab json中https://android-kotlin-fun-mars-server.appspot.com/photos是这样的:

[
  {
    "id": "424905",
    "img_src": "https://mars.jpl.nasa.gov/msl-raw-images/msss/01000/mcam/1000MR0044631300503690E01_DXXX.jpg"
  },
  {
    "id": "424906",
    "img_src": "https://mars.jpl.nasa.gov/msl-raw-images/msss/01000/mcam/1000ML0044631300305227E03_DXXX.jpg"
  },
  {
    "id": "424907",
    "img_src": "https://mars.jpl.nasa.gov/msl-raw-images/msss/01000/mcam/1000MR0044631290503689E01_DXXX.jpg"
  },
  {
    "id": "424908",
    "img_src": "https://mars.jpl.nasa.gov/msl-raw-images/msss/01000/mcam/1000ML0044631290305226E03_DXXX.jpg"
  }
]

MarshPhoto 数据类:

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class MarsPhoto(
    val id: String,
    @SerialName(value = "img_src")
    val imgSrc: String
)

MarsApi服务:

import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
import kotlinx.serialization.json.Json
import okhttp3.MediaType.Companion.toMediaType
import retrofit2.Retrofit
import retrofit2.http.GET

private const val BASE_URL =
    "https://android-kotlin-fun-mars-server.appspot.com"
private val retrofit = Retrofit.Builder()
    .addConverterFactory(Json.asConverterFactory("application/json".toMediaType()))
    .baseUrl(BASE_URL)
    .build()

interface MarsApiService {
    @GET("photos")
    suspend fun getPhotos(): List<MarsPhoto>
}

object MarsApi {
    val retrofitService : MarsApiService by lazy {
        retrofit.create(MarsApiService::class.java)
    }
}

火星视图模型:

import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.marsphotos.network.MarsApi
import kotlinx.coroutines.launch
import java.io.IOException

sealed interface MarsUiState {
    data class Success(val photos: String) : MarsUiState
    object Error: MarsUiState
    object Loading: MarsUiState
}

class MarsViewModel : ViewModel() {
    /** The mutable State that stores the status of the most recent request */
    var marsUiState: MarsUiState by mutableStateOf(MarsUiState.Loading)
        private set

    /**
     * Call getMarsPhotos() on init so we can display status immediately.
     */
    init {
        getMarsPhotos()
    }

    /**
     * Gets Mars photos information from the Mars API Retrofit service and updates the
     * [MarsPhoto] [List] [MutableList].
     */
    fun getMarsPhotos() {
        viewModelScope.launch {
            marsUiState = try {
                val listResult = MarsApi.retrofitService.getPhotos()
                MarsUiState.Success(
                    "Success: ${listResult.size} Mars photos retrieved"
                )
            }
            catch (e: IOException) {
                MarsUiState.Error
            }
        }
    }
}

他们的代码不会崩溃并按预期工作。无法理解为什么我的代码会崩溃

android kotlin retrofit retrofit2
1个回答
0
投票

啊啊,仅供参考,

price: Long
在你的情况下是可以接受的。无论如何,你也可以使用 Int。

© www.soinside.com 2019 - 2024. All rights reserved.