我正在做一个使用API:https://gadhagod.github.io/Hyrule-Compendium-API/#/的应用程序.在点击列表中的项目时,我try 绘制项目细节之前,一切都很正常.我没有很好地处理我试图访问项的属性的方式,但我不知道我到底在哪里出错.我将详细说明导航流程,但我不知道这是否满足于询问

CompendiumApi

interface CompendiumApi {

    @GET("all?game=2")
    suspend fun getTearsAllEntries(): CompendiumList

    @GET("all?game=1")
    suspend fun getBreathAllEntries(): CompendiumList

    @GET("entry/{id}")
    suspend fun getItemInfo(
        @Path("id") id: Int
    ): Data
}

CompendiumRepository

@ActivityScoped
class CompendiumRepository @Inject constructor(
   private val api: CompendiumApi
){
   suspend fun getTearsAllEntries(): Resource<CompendiumList> {
      val response = try {
         api.getTearsAllEntries()
      } catch (e: Exception) {
         return Resource.Error("An unknown error occurred.")
      }
      return Resource.Success(response)
   }

   suspend fun getBreathAllEntries(): Resource<CompendiumList> {
      val response = try {
         api.getBreathAllEntries()
      } catch (e: Exception) {
         return Resource.Error("An unknown error occurred.")
      }
      return Resource.Success(response)
   }

   suspend fun getItemInfo(id: Int) : Resource<Data> {
      val response = try {
         Log.d("getItemInfo",api.getItemInfo(id).toString())
         api.getItemInfo(id)
      } catch (e: Exception) {
         return Resource.Error("An unknow error ocurred.")
      }
      return Resource.Success(response)
   }
}

CompendiumDetailViewModel

@HiltViewModel
class CompendiumDetailViewModel @Inject constructor(
   private val repository: CompendiumRepository
) : ViewModel() {

   suspend fun getItemInfo(id: Int): Resource<Data> {
      return repository.getItemInfo(id)
   }
}

CompendiumDetailScreen

@Composable
fun CompendiumDetailCard(
   id: Int,
   viewModel: CompendiumDetailViewModel = hiltViewModel()
) {
   val itemInfo = produceState<Resource<Data>>(initialValue = Resource.Loading()) {
      value = viewModel.getItemInfo(id)
   }.value
   Log.d("itemDetailScreen", "item clicked: ${itemInfo.data.toString()}")
   ElevatedCard(
      elevation = CardDefaults.cardElevation(
         defaultElevation = 6.dp
      ),
      modifier = Modifier
         .fillMaxWidth()
   ) {
      ItemDetailStateWrapper(
         itemInfo = itemInfo,
         loadingModifier = Modifier
            .size(100.dp)
            .align(Alignment.CenterHorizontally)
            .padding(
               top = 16.dp,
               start = 16.dp,
               end = 16.dp,
               bottom = 16.dp
            )
      )
   }
}

@Composable
fun ItemDetailStateWrapper(
   itemInfo: Resource<Data>,
   loadingModifier: Modifier = Modifier
){
   when(itemInfo){
      is Resource.Success -> {
         ItemDetailInfo(
            itemInfo = itemInfo.data!!
         )
      }
      is Resource.Error -> {
         Text(
            text = itemInfo.message!!,
            color = Color.Red,
         )
      }
      is Resource.Loading -> {
         CircularProgressIndicator(
            color = MaterialTheme.colorScheme.primary,
            modifier = loadingModifier
         )
      }
   }
}

@Composable
fun ItemDetailInfo(
   itemInfo: Data
){
   Text(text = itemInfo.name ?: "No name") //"No name painted"
}

MainActivity using for navigate

@AndroidEntryPoint
class MainActivity : ComponentActivity() {
   override fun onCreate(savedInstanceState: Bundle?) {
      super.onCreate(savedInstanceState)
      window.statusBarColor = getColor(R.color.black)
      setContent {
         ZeldaCompendiumTheme {
            val navController = rememberNavController()
            NavHost(
               navController = navController,
               startDestination = "compendium_navigation"
            ) {
               composable("compendium_navigation") {
                  HomeContainer(navController = navController)
               }
               composable("compendium_tears_screen") {
                  TearsContainer(
                     navController = navController
                  )
               }
               composable("compendium_breath_screen") {
                  BreathContainer(
                     navController = navController
                  )
               }
               composable(
                  "item_detail_screen/{id}",
                  arguments = listOf(
                     navArgument("id") {
                        type = NavType.IntType
                     }
                  )
               ) {
                  val id = remember {
                     it.arguments?.getInt("id")
                  }
                  if (id != null) {
                     CompendiumDetailCard(
                        id = id,
                     )
                  }
               }
            }
         }
      }
   }
}

CompendiumList

data class CompendiumList(
   val data: List<Data>
)

CompendiumListEntry

data class CompendiumListEntry (
   val compendiumName: String,
   val category: String,
   val imageURL: String,
   val id: Int
)

Data

data class Data(
   val category: String,
   @SerializedName("common_location") val commonLocations: List<String>,
   @SerializedName("cooking_effect") val cookingEffect: String,
   val description: String,
   val dlc: Boolean,
   val drops: List<String>,
   val edible: Boolean,
   @SerializedName("fuse_attack_power") val fuseAttackPower: Int,
   @SerializedName("hearts_recovered")val heartsRecovered: Double,
   val id: Int,
   val image: String,
   val name: String,
   val properties: Properties
)

我必须指出的是,我通过控制台绘制与屏幕交互时发出的请求,当单击某个项目时,通过控制台绘制所选项目的正确URL:

enter image description here

推荐答案

我认为,API返回的JSON struct 与您要将JSON解析成的数据类 struct 之间存在简单的不匹配.

您将需要引入新的数据类或更新您的CompendiumListItem类,如下所示:

data class CompendiumListEntry (
   val data: Data
)

然后将此数据类设置为getItemInfo API函数的类型:

@GET("entry/{id}")
suspend fun getItemInfo(
    @Path("id") id: Int
): CompendiumListEntry

相应地更新对该函数的所有调用:

suspend fun getItemInfo(id: Int) : Resource<CompendiumListEntry> {
    val response = try {
       Log.d("getItemInfo",api.getItemInfo(id).data.toString())
       api.getItemInfo(id)
    } catch (e: Exception) {
       return Resource.Error("An unknow error ocurred.")
    }
    return Resource.Success(response)
}

在您的Composable中,您可能必须这样做(我不知道您的资源类是如何实现的):

val itemInfo = produceState<Resource<Data>>(initialValue = Resource.Loading()) {
    value = viewModel.getItemInfo(id)
}.value
Log.d("itemDetailScreen", "item clicked: ${itemInfo.data.data.toString()}")

Android相关问答推荐

在Android Studio中陷入了不兼容的Gradle版本的循环

Android 14上的慢速意图广播交付

无法使用MenuItemColors.Copy()

如何阻止Gradle在编译时生成app-metadata.properties

如何将两个变量传递给Nav主机,然后将其传递给另一个屏幕?

OutlinedTextField仅显示一次

Android 12+BLE字节不同

Android studio应用判断无法打开离线数据库

将输出写入已发布的 Android 应用程序中的日志(log)文件?

Android 应用程序从 Android Studio 安装,但不是作为 .apk 在外部安装.抛出java.lang.UnsatisfiedLinkError

在 MVVM Jetpack Compose 上添加依赖项时出现重复类错误

设置背景图片组成Column

视觉转换后获取文本

Android CompanionDeviceManager 永远找不到任何附近的蓝牙设备

Jetpack Compose Canvas drawText colored颜色 混合?

如何在 Jetpack compose 中将 Canvas 中的文本居中?

在 Compose 中使用 DeepLink 会导致无法向后导航

如何让用户与任意应用程序共享文件?

如何删除 Ktor 客户端 2.0.0 的默认标头

Jetpack Compose Tapjacking:过滤对模糊 UI 的touch