使用 corrutines 的 Kotlin retrofit2 连接
Kotlin retrofit2 connection using corrutines
我正在使用 Kotlin 开发一个应用程序,它使用 Retrofit2 库与 PokeApi 连接。
我曾尝试使用 corrutines 来做到这一点,但在使用 corrutines 之前,我通过异步调用获得的响应为空。
调用 API 的我的 dataProvider 的代码如下:
DataProvider.kt
/**
* Metodo que permite obtener un LiveData con la informacion del siguiente pokemon por id, que será la posible evolución.
*/
fun viewPokemonEvolution(id: Long): LiveData<PokemonFormResponse>? {
var remotePokemonEvolutionFormData : LiveData<PokemonFormResponse>? = null
var call: Response<LiveData<PokemonFormResponse>>
var data: LiveData<PokemonFormResponse>?
CoroutineScope(Dispatchers.Main).launch {
call = remoteDataSource.downloadPokemonViewedData(id)
data = call.body()
if(call.isSuccessful){
remotePokemonEvolutionFormData = data
}
}
return remotePokemonEvolutionFormData!!
}
我的APIclass
interface PokemonApi {
@GET("pokemon-form/{id}")
suspend fun getPokemonInfo(@Path("id") idPokemon: Long): Response<LiveData<PokemonFormResponse>>
@GET("pokemon/{name}")
suspend fun getPokemonExtendedInfo(@Path("name") pokemonName: String): Response<LiveData<PokemonExtendedInfoResponse>>
}
我的数据class
PokemoFormResponse.kt
data class PokemonFormResponse(
@SerializedName("form_name")
val formName: String,
@SerializedName("form_names")
val formNames: List<Any>,
@SerializedName("form_order")
val formOrder: Int,
@SerializedName("id")
val id: Int,
@SerializedName("is_battle_only")
val isBattleOnly: Boolean,
@SerializedName("is_default")
val isDefault: Boolean,
@SerializedName("is_mega")
val isMega: Boolean,
@SerializedName("name")
val name: String,
@SerializedName("names")
val names: List<Any>,
@SerializedName("order")
val order: Int,
@SerializedName("pokemon")
val pokemon: PokemonUrl,
@SerializedName("sprites")
val sprites: Sprites,
@SerializedName("version_group")
val versionGroup: VersionGroup
){
fun idFilledWithZero(): String {
return String.format("%03d", id)
}
}
我的远程数据源
IRemoteDataSource.kt
interface IRemoteDataSource {
suspend fun downloadPokemonViewedData(id: Long): Response<LiveData<PokemonFormResponse>>
suspend fun downloadPokemonCatchedData(name: String): Response<LiveData<PokemonExtendedInfoResponse>>
}
interface ILocalDataSource {
fun getPokemonList(): LiveData<List<Pokemon>>
fun getPokemonById(idPokemon: Long): LiveData<Pokemon>
suspend fun insertPokemon(pokemon: Pokemon)
}
以及在 LocalDataSource 中调用 room 的 DAO:
@Dao
interface PokemonDao {
@Query("SELECT * from listaPokemon")
fun getAll(): LiveData<List<Pokemon>>
@Insert(onConflict = REPLACE)
fun insert(pokemon:Pokemon)
@Insert(onConflict = REPLACE)
fun insertAll(vararg pokemons: Pokemon)
@Query("SELECT * from listaPokemon WHERE id = :pokemonId")
fun getById(pokemonId: Long): LiveData<Pokemon>
}
我希望你能提出一些修复实现的方法,因为使用 corrutines 而不是异步调用是更好的方法。
我添加了 debugg 的捕获,显示所有属性为 null
希望能帮到你,如果是这样的话先谢谢了!
[编辑]
添加了 RemoteDataSource`
class RemoteDataSource : IRemoteDataSource{
val BASE_URL = "https://pokeapi.co/api/v2/"
val TIMEOUT: Long = 30
var apiServices: PokemonApi
init {
val httpClient : OkHttpClient.Builder = OkHttpClient.Builder()
httpClient.connectTimeout(TIMEOUT, TimeUnit.SECONDS)
httpClient.readTimeout(TIMEOUT, TimeUnit.SECONDS)
httpClient.writeTimeout(TIMEOUT, TimeUnit.SECONDS)
val retrofit: Retrofit = Retrofit.Builder()
//Se utiliza el networkIO como ejecutor de Retrofit
.callbackExecutor(AppExecutors.networkIO)
.client(httpClient.build())
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(BASE_URL)
.build()
apiServices = retrofit.create(PokemonApi::class.java)
}
/**
* Función tipo utilizando retrofit para obtener datos desde una api remota
*
* Simplicación de las funciones mediante las corrutinas
*/
override suspend fun downloadPokemonViewedData(id: Long): Response<LiveData<PokemonFormResponse>> = withContext(Dispatchers.Main) {
apiServices.getPokemonInfo(
id
)
}
override suspend fun downloadPokemonCatchedData(name: String): Response<LiveData<PokemonExtendedInfoResponse>> = withContext(Dispatchers.Main){
apiServices.getPokemonExtendedInfo(
name
)
}
和界面
IRemoteDatasource.kt
interface IRemoteDataSource {
suspend fun downloadPokemonViewedData(id: Long): Response<LiveData<PokemonFormResponse>>
suspend fun downloadPokemonCatchedData(name: String): Response<LiveData<PokemonExtendedInfoResponse>>
}
在尝试实施@Arpit Shukla 解决方案后,由于 return 和 LiveData(Unit ) 类型,而不是像更改之前那样只是单位。
所以我像这样在 DetailFragment.kt 上调用那些方法的结果,但不起作用
精灵宝可梦DetailFragment.kt
....
fun observeViewModel(){
Log.d("info", "Entra en observeViewModel")
pokemonListViewModel?.selectedPokemonIdFromVM?.observe(viewLifecycleOwner, Observer { selectedId ->
selectedId?.let { pokemonSelectedId ->
pokemonDetailViewModel?.loadPokemonInfo(pokemonSelectedId)
//Al seleccionar el pokemeon actualizamos tambien el evlution del ViewModelDetail
pokemonDetailViewModel?.loadPokemonEvolution(pokemonSelectedId)
}
})
?:
pokemonIdFromBundle?.let {
pokemonDetailViewModel?.loadPokemonInfo(it)
pokemonDetailViewModel?.loadPokemonEvolution(it)
}
.....
所以我试着观察响应,所以它是一个 LiveData,但我不知道我应该在回调上做什么。
我的其他class如下
PokemonApi.kt
interface PokemonApi {
@GET("pokemon-form/{id}")
suspend fun getPokemonInfo(@Path("id") idPokemon: Long): PokemonFormResponse
@GET("pokemon/{name}")
suspend fun getPokemonExtendedInfo(@Path("name") pokemonName: String): PokemonExtendedInfoResponse
}
IRemoteDataSource.kt
interface IRemoteDataSource {
suspend fun downloadPokemonViewedData(id: Long): PokemonFormResponse
suspend fun downloadPokemonCatchedData(name: String): PokemonExtendedInfoResponse
}
RemoteDataSource.kt
class RemoteDataSource : IRemoteDataSource{
val BASE_URL = "https://pokeapi.co/api/v2/"
val TIMEOUT: Long = 30
var apiServices: PokemonApi
init {
val httpClient : OkHttpClient.Builder = OkHttpClient.Builder()
httpClient.connectTimeout(TIMEOUT, TimeUnit.SECONDS)
httpClient.readTimeout(TIMEOUT, TimeUnit.SECONDS)
httpClient.writeTimeout(TIMEOUT, TimeUnit.SECONDS)
val retrofit: Retrofit = Retrofit.Builder()
//Se utiliza el networkIO como ejecutor de Retrofit
.callbackExecutor(AppExecutors.networkIO)
.client(httpClient.build())
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(BASE_URL)
.build()
apiServices = retrofit.create(PokemonApi::class.java)
}
/**
* Función tipo utilizando retrofit para obtener datos desde una api remota
*
* Simplicación de las funciones mediante las corrutinas
*/
override suspend fun downloadPokemonViewedData(id: Long): PokemonFormResponse = withContext(Dispatchers.Main) {
apiServices.getPokemonInfo(
id
)
}
override suspend fun downloadPokemonCatchedData(name: String): PokemonExtendedInfoResponse = withContext(Dispatchers.Default){
apiServices.getPokemonExtendedInfo(
name
)
}
}
关于本地数据库。
精灵宝可梦道
@Dao
interface PokemonDao {
@Query("SELECT * from listaPokemon")
fun getAll(): List<Pokemon>
@Insert(onConflict = REPLACE)
fun insert(pokemon:Pokemon)
@Insert(onConflict = REPLACE)
fun insertAll(vararg pokemons: Pokemon)
@Query("SELECT * from listaPokemon WHERE id = :pokemonId")
fun getById(pokemonId: Long): Pokemon
}
AppDatabase.kt
//Definición de la DB ROOM y sus entities
@Database(entities = arrayOf(Pokemon::class), version = 1)
abstract class AppDatabase : RoomDatabase() {
//Singleton de la DB
companion object {
private var instance: AppDatabase? = null
fun getInstance(context: Context):AppDatabase? {
if (instance == null){
synchronized(AppDatabase::class){
//datos del objeto sql
instance = Room.databaseBuilder(context.applicationContext, AppDatabase::class.java, "pokedexcanner.db")
.fallbackToDestructiveMigration().build()
}
}
return instance
}
}
//obtención de los DAOs de la DB
abstract fun getPokemonDao(): PokemonDao
}
ILocalDataSource.kt
interface ILocalDataSource {
fun getPokemonList(): List<Pokemon>
fun getPokemonById(idPokemon: Long): Pokemon
suspend fun insertPokemon(pokemon: Pokemon)
}
LocalDataSource.kt
class LocalDataSource : ILocalDataSource{
lateinit var pokemonDao: PokemonDao
constructor(context: Context){
val database = AppDatabase.getInstance(context)
database?.let {
pokemonDao = database.getPokemonDao()
}
}
override fun getPokemonList(): List<Pokemon> {
return pokemonDao.getAll()
}
override fun getPokemonById(idPokemon: Long): Pokemon{
return pokemonDao.getById(idPokemon)
}
override suspend fun insertPokemon(pokemon: Pokemon) {
pokemonDao.insert(pokemon)
}
}
实体方面:
Pokemon.kt
@Entity(tableName = "listaPokemon")
data class Pokemon (@PrimaryKey var id: Long?,
@ColumnInfo(name = "name") var nombre: String,
@ColumnInfo(name = "image") var imagen: String?,
@ColumnInfo(name = "height") var altura: Float?,
@ColumnInfo(name = "weight") var peso: Float?
){
fun idFilledWithZero(): String {
return String.format("%03d", id)
}
constructor():this(null,"?",null,null,null)
}
`
PokemonFormResponse.kt
data class PokemonFormResponse(
@SerializedName("form_name")
val formName: String,
@SerializedName("form_names")
val formNames: List<Any>,
@SerializedName("form_order")
val formOrder: Int,
@SerializedName("id")
val id: Int,
@SerializedName("is_battle_only")
val isBattleOnly: Boolean,
@SerializedName("is_default")
val isDefault: Boolean,
@SerializedName("is_mega")
val isMega: Boolean,
@SerializedName("name")
val name: String,
@SerializedName("names")
val names: List<Any>,
@SerializedName("order")
val order: Int,
@SerializedName("pokemon")
val pokemon: PokemonUrl,
@SerializedName("sprites")
val sprites: Sprites,
@SerializedName("version_group")
val versionGroup: VersionGroup
){
fun idFilledWithZero(): String {
return String.format("%03d", id)
}
}
PokemonExtendedInfoResponse.kt
data class PokemonExtendedInfoResponse(
@SerializedName("abilities")
val abilities: List<Ability>,
@SerializedName("base_experience")
val baseExperience: Int,
@SerializedName("forms")
val forms: List<Form>,
@SerializedName("game_indices")
val gameIndices: List<GameIndice>,
@SerializedName("height")
val height: Float,
@SerializedName("held_items")
val heldItems: List<HeldItem>,
@SerializedName("id")
val id: Int,
@SerializedName("is_default")
val isDefault: Boolean,
@SerializedName("location_area_encounters")
val locationAreaEncounters: String,
@SerializedName("moves")
val moves: List<Move>,
@SerializedName("name")
val name: String,
@SerializedName("order")
val order: Int,
@SerializedName("species")
val species: Species,
@SerializedName("sprites")
val sprites: SpritesX,
@SerializedName("stats")
val stats: List<Stat>,
@SerializedName("types")
val types: List<Type>,
@SerializedName("weight")
val weight: Float
)
因此,如果您知道某种处理这种情况的方法,请提前致谢!
我正在使用 Kotlin 开发一个应用程序,它使用 Retrofit2 库与 PokeApi 连接。
我曾尝试使用 corrutines 来做到这一点,但在使用 corrutines 之前,我通过异步调用获得的响应为空。
调用 API 的我的 dataProvider 的代码如下:
DataProvider.kt
/**
* Metodo que permite obtener un LiveData con la informacion del siguiente pokemon por id, que será la posible evolución.
*/
fun viewPokemonEvolution(id: Long): LiveData<PokemonFormResponse>? {
var remotePokemonEvolutionFormData : LiveData<PokemonFormResponse>? = null
var call: Response<LiveData<PokemonFormResponse>>
var data: LiveData<PokemonFormResponse>?
CoroutineScope(Dispatchers.Main).launch {
call = remoteDataSource.downloadPokemonViewedData(id)
data = call.body()
if(call.isSuccessful){
remotePokemonEvolutionFormData = data
}
}
return remotePokemonEvolutionFormData!!
}
我的APIclass
interface PokemonApi {
@GET("pokemon-form/{id}")
suspend fun getPokemonInfo(@Path("id") idPokemon: Long): Response<LiveData<PokemonFormResponse>>
@GET("pokemon/{name}")
suspend fun getPokemonExtendedInfo(@Path("name") pokemonName: String): Response<LiveData<PokemonExtendedInfoResponse>>
}
我的数据class
PokemoFormResponse.kt
data class PokemonFormResponse(
@SerializedName("form_name")
val formName: String,
@SerializedName("form_names")
val formNames: List<Any>,
@SerializedName("form_order")
val formOrder: Int,
@SerializedName("id")
val id: Int,
@SerializedName("is_battle_only")
val isBattleOnly: Boolean,
@SerializedName("is_default")
val isDefault: Boolean,
@SerializedName("is_mega")
val isMega: Boolean,
@SerializedName("name")
val name: String,
@SerializedName("names")
val names: List<Any>,
@SerializedName("order")
val order: Int,
@SerializedName("pokemon")
val pokemon: PokemonUrl,
@SerializedName("sprites")
val sprites: Sprites,
@SerializedName("version_group")
val versionGroup: VersionGroup
){
fun idFilledWithZero(): String {
return String.format("%03d", id)
}
}
我的远程数据源
IRemoteDataSource.kt
interface IRemoteDataSource {
suspend fun downloadPokemonViewedData(id: Long): Response<LiveData<PokemonFormResponse>>
suspend fun downloadPokemonCatchedData(name: String): Response<LiveData<PokemonExtendedInfoResponse>>
}
interface ILocalDataSource {
fun getPokemonList(): LiveData<List<Pokemon>>
fun getPokemonById(idPokemon: Long): LiveData<Pokemon>
suspend fun insertPokemon(pokemon: Pokemon)
}
以及在 LocalDataSource 中调用 room 的 DAO:
@Dao
interface PokemonDao {
@Query("SELECT * from listaPokemon")
fun getAll(): LiveData<List<Pokemon>>
@Insert(onConflict = REPLACE)
fun insert(pokemon:Pokemon)
@Insert(onConflict = REPLACE)
fun insertAll(vararg pokemons: Pokemon)
@Query("SELECT * from listaPokemon WHERE id = :pokemonId")
fun getById(pokemonId: Long): LiveData<Pokemon>
}
我希望你能提出一些修复实现的方法,因为使用 corrutines 而不是异步调用是更好的方法。
我添加了 debugg 的捕获,显示所有属性为 null
希望能帮到你,如果是这样的话先谢谢了!
[编辑]
添加了 RemoteDataSource`
class RemoteDataSource : IRemoteDataSource{
val BASE_URL = "https://pokeapi.co/api/v2/"
val TIMEOUT: Long = 30
var apiServices: PokemonApi
init {
val httpClient : OkHttpClient.Builder = OkHttpClient.Builder()
httpClient.connectTimeout(TIMEOUT, TimeUnit.SECONDS)
httpClient.readTimeout(TIMEOUT, TimeUnit.SECONDS)
httpClient.writeTimeout(TIMEOUT, TimeUnit.SECONDS)
val retrofit: Retrofit = Retrofit.Builder()
//Se utiliza el networkIO como ejecutor de Retrofit
.callbackExecutor(AppExecutors.networkIO)
.client(httpClient.build())
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(BASE_URL)
.build()
apiServices = retrofit.create(PokemonApi::class.java)
}
/**
* Función tipo utilizando retrofit para obtener datos desde una api remota
*
* Simplicación de las funciones mediante las corrutinas
*/
override suspend fun downloadPokemonViewedData(id: Long): Response<LiveData<PokemonFormResponse>> = withContext(Dispatchers.Main) {
apiServices.getPokemonInfo(
id
)
}
override suspend fun downloadPokemonCatchedData(name: String): Response<LiveData<PokemonExtendedInfoResponse>> = withContext(Dispatchers.Main){
apiServices.getPokemonExtendedInfo(
name
)
}
和界面
IRemoteDatasource.kt
interface IRemoteDataSource {
suspend fun downloadPokemonViewedData(id: Long): Response<LiveData<PokemonFormResponse>>
suspend fun downloadPokemonCatchedData(name: String): Response<LiveData<PokemonExtendedInfoResponse>>
}
在尝试实施@Arpit Shukla 解决方案后,由于 return 和 LiveData(Unit ) 类型,而不是像更改之前那样只是单位。
所以我像这样在 DetailFragment.kt 上调用那些方法的结果,但不起作用
精灵宝可梦DetailFragment.kt
....
fun observeViewModel(){
Log.d("info", "Entra en observeViewModel")
pokemonListViewModel?.selectedPokemonIdFromVM?.observe(viewLifecycleOwner, Observer { selectedId ->
selectedId?.let { pokemonSelectedId ->
pokemonDetailViewModel?.loadPokemonInfo(pokemonSelectedId)
//Al seleccionar el pokemeon actualizamos tambien el evlution del ViewModelDetail
pokemonDetailViewModel?.loadPokemonEvolution(pokemonSelectedId)
}
})
?:
pokemonIdFromBundle?.let {
pokemonDetailViewModel?.loadPokemonInfo(it)
pokemonDetailViewModel?.loadPokemonEvolution(it)
}
.....
所以我试着观察响应,所以它是一个 LiveData,但我不知道我应该在回调上做什么。
我的其他class如下
PokemonApi.kt
interface PokemonApi {
@GET("pokemon-form/{id}")
suspend fun getPokemonInfo(@Path("id") idPokemon: Long): PokemonFormResponse
@GET("pokemon/{name}")
suspend fun getPokemonExtendedInfo(@Path("name") pokemonName: String): PokemonExtendedInfoResponse
}
IRemoteDataSource.kt
interface IRemoteDataSource {
suspend fun downloadPokemonViewedData(id: Long): PokemonFormResponse
suspend fun downloadPokemonCatchedData(name: String): PokemonExtendedInfoResponse
}
RemoteDataSource.kt
class RemoteDataSource : IRemoteDataSource{
val BASE_URL = "https://pokeapi.co/api/v2/"
val TIMEOUT: Long = 30
var apiServices: PokemonApi
init {
val httpClient : OkHttpClient.Builder = OkHttpClient.Builder()
httpClient.connectTimeout(TIMEOUT, TimeUnit.SECONDS)
httpClient.readTimeout(TIMEOUT, TimeUnit.SECONDS)
httpClient.writeTimeout(TIMEOUT, TimeUnit.SECONDS)
val retrofit: Retrofit = Retrofit.Builder()
//Se utiliza el networkIO como ejecutor de Retrofit
.callbackExecutor(AppExecutors.networkIO)
.client(httpClient.build())
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(BASE_URL)
.build()
apiServices = retrofit.create(PokemonApi::class.java)
}
/**
* Función tipo utilizando retrofit para obtener datos desde una api remota
*
* Simplicación de las funciones mediante las corrutinas
*/
override suspend fun downloadPokemonViewedData(id: Long): PokemonFormResponse = withContext(Dispatchers.Main) {
apiServices.getPokemonInfo(
id
)
}
override suspend fun downloadPokemonCatchedData(name: String): PokemonExtendedInfoResponse = withContext(Dispatchers.Default){
apiServices.getPokemonExtendedInfo(
name
)
}
}
关于本地数据库。
精灵宝可梦道
@Dao
interface PokemonDao {
@Query("SELECT * from listaPokemon")
fun getAll(): List<Pokemon>
@Insert(onConflict = REPLACE)
fun insert(pokemon:Pokemon)
@Insert(onConflict = REPLACE)
fun insertAll(vararg pokemons: Pokemon)
@Query("SELECT * from listaPokemon WHERE id = :pokemonId")
fun getById(pokemonId: Long): Pokemon
}
AppDatabase.kt
//Definición de la DB ROOM y sus entities
@Database(entities = arrayOf(Pokemon::class), version = 1)
abstract class AppDatabase : RoomDatabase() {
//Singleton de la DB
companion object {
private var instance: AppDatabase? = null
fun getInstance(context: Context):AppDatabase? {
if (instance == null){
synchronized(AppDatabase::class){
//datos del objeto sql
instance = Room.databaseBuilder(context.applicationContext, AppDatabase::class.java, "pokedexcanner.db")
.fallbackToDestructiveMigration().build()
}
}
return instance
}
}
//obtención de los DAOs de la DB
abstract fun getPokemonDao(): PokemonDao
}
ILocalDataSource.kt
interface ILocalDataSource {
fun getPokemonList(): List<Pokemon>
fun getPokemonById(idPokemon: Long): Pokemon
suspend fun insertPokemon(pokemon: Pokemon)
}
LocalDataSource.kt
class LocalDataSource : ILocalDataSource{
lateinit var pokemonDao: PokemonDao
constructor(context: Context){
val database = AppDatabase.getInstance(context)
database?.let {
pokemonDao = database.getPokemonDao()
}
}
override fun getPokemonList(): List<Pokemon> {
return pokemonDao.getAll()
}
override fun getPokemonById(idPokemon: Long): Pokemon{
return pokemonDao.getById(idPokemon)
}
override suspend fun insertPokemon(pokemon: Pokemon) {
pokemonDao.insert(pokemon)
}
}
实体方面:
Pokemon.kt
@Entity(tableName = "listaPokemon")
data class Pokemon (@PrimaryKey var id: Long?,
@ColumnInfo(name = "name") var nombre: String,
@ColumnInfo(name = "image") var imagen: String?,
@ColumnInfo(name = "height") var altura: Float?,
@ColumnInfo(name = "weight") var peso: Float?
){
fun idFilledWithZero(): String {
return String.format("%03d", id)
}
constructor():this(null,"?",null,null,null)
}
` PokemonFormResponse.kt
data class PokemonFormResponse(
@SerializedName("form_name")
val formName: String,
@SerializedName("form_names")
val formNames: List<Any>,
@SerializedName("form_order")
val formOrder: Int,
@SerializedName("id")
val id: Int,
@SerializedName("is_battle_only")
val isBattleOnly: Boolean,
@SerializedName("is_default")
val isDefault: Boolean,
@SerializedName("is_mega")
val isMega: Boolean,
@SerializedName("name")
val name: String,
@SerializedName("names")
val names: List<Any>,
@SerializedName("order")
val order: Int,
@SerializedName("pokemon")
val pokemon: PokemonUrl,
@SerializedName("sprites")
val sprites: Sprites,
@SerializedName("version_group")
val versionGroup: VersionGroup
){
fun idFilledWithZero(): String {
return String.format("%03d", id)
}
}
PokemonExtendedInfoResponse.kt
data class PokemonExtendedInfoResponse(
@SerializedName("abilities")
val abilities: List<Ability>,
@SerializedName("base_experience")
val baseExperience: Int,
@SerializedName("forms")
val forms: List<Form>,
@SerializedName("game_indices")
val gameIndices: List<GameIndice>,
@SerializedName("height")
val height: Float,
@SerializedName("held_items")
val heldItems: List<HeldItem>,
@SerializedName("id")
val id: Int,
@SerializedName("is_default")
val isDefault: Boolean,
@SerializedName("location_area_encounters")
val locationAreaEncounters: String,
@SerializedName("moves")
val moves: List<Move>,
@SerializedName("name")
val name: String,
@SerializedName("order")
val order: Int,
@SerializedName("species")
val species: Species,
@SerializedName("sprites")
val sprites: SpritesX,
@SerializedName("stats")
val stats: List<Stat>,
@SerializedName("types")
val types: List<Type>,
@SerializedName("weight")
val weight: Float
)
因此,如果您知道某种处理这种情况的方法,请提前致谢!