如何在Jetpack Compose中通过Retrofit多参数GET请求获取词汇数据
问题描述
我正在开发一款面向初学者的英语学习APP,现在需要通过Retrofit发起GET请求,携带Level和Unit两个查询参数,从数据库获取对应词汇数据。接口示例为https://adeega.xisaabso.online/Api/Article_vocabulary.php?Level=1&Unit=1,以下是我的现有代码,求解决方案:
Vocabulary_Api.kt
const val Vocabulary = "https://adeega.xisaabso.online/Api/" interface getVocabularies { @GET("Article_vocabulary.php") fun getVocabularies(): Call<Vocabularies> } object getVocabulariesInstance { val getVocabulariesSections: getVocabularies init { val retrofit = Retrofit.Builder() .baseUrl(Vocabulary) .addConverterFactory(GsonConverterFactory.create()) .build() getVocabulariesSections = retrofit.create(getVocabularies::class.java) } }
Vocabulary.kt
val users = getVocabulariesInstance.getVocabulariesSections.getVocabularies() val data = remember { mutableStateOf(Vocabularies()) } users.enqueue(object: Callback<Vocabularies> { override fun onResponse( call: Call<Vocabularies>, response: Response<Vocabularies> ) { val userData = response.body() if(userData != null) { data.value = userData } } override fun onFailure(call: Call<Vocabularies>, t: Throwable) { Toast.makeText(context, t.toString(), Toast.LENGTH_SHORT).show() } }) LazyColumn( contentPadding = PaddingValues( horizontal = 12.dp, /*vertical = 0.dp*/ ), verticalArrangement = Arrangement.spacedBy(10.dp) ) { items(data.value) { item -> Cards_Vocabulary(data = item, navController) //Divider(color = Color.Gray, thickness = 1.dp) } } // END LazyColumn
database.php
if(!empty($_GET['Level']) && !empty($_GET['Unit'])) { $Level = (int)$_GET['Level']; $Unit = (int)$_GET['Unit']; $Article = $pdo->prepare("SELECT * FROM App_vocabularies WHERE LevelID = ? AND UnitID = ?"); $Article->bindParam(1, $Level); $Article->bindParam(2, $Unit); $Article->execute(); $Article = $Article->fetchAll(PDO::FETCH_OBJ); echo json_encode($Article); }
解决方案
1. 修改Retrofit接口,添加查询参数
当前接口未传递Level和Unit参数,需要通过@Query注解添加这两个参数,同时调整返回类型为列表(PHP接口返回的是词汇数组):
const val Vocabulary = "https://adeega.xisaabso.online/Api/" // 接口名遵循大驼峰规范,改为VocabularyApi interface VocabularyApi { @GET("Article_vocabulary.php") fun getVocabularies( @Query("Level") level: Int, @Query("Unit") unit: Int ): Call<List<VocabularyItem>> } object VocabularyApiInstance { val api: VocabularyApi init { val retrofit = Retrofit.Builder() .baseUrl(Vocabulary) .addConverterFactory(GsonConverterFactory.create()) .build() api = retrofit.create(VocabularyApi::class.java) } }
2. 创建单个词汇的数据模型类
根据数据库字段创建VocabularyItem类,确保属性名和JSON返回的字段一致:
data class VocabularyItem( val id: Int, val LevelID: Int, val UnitID: Int, val word: String, val meaning: String, // 添加其他数据库对应的字段 )
3. 调整接口调用逻辑
传入Level和Unit参数,同时将状态变量改为列表类型:
// 示例值,实际可从导航参数或用户选择获取 val targetLevel = 1 val targetUnit = 1 val users = VocabularyApiInstance.api.getVocabularies(targetLevel, targetUnit) val data = remember { mutableStateOf(emptyList<VocabularyItem>()) } users.enqueue(object: Callback<List<VocabularyItem>> { override fun onResponse( call: Call<List<VocabularyItem>>, response: Response<List<VocabularyItem>> ) { val userData = response.body() if(userData != null) { data.value = userData } else { Toast.makeText(context, "未获取到对应词汇数据", Toast.LENGTH_SHORT).show() } } override fun onFailure(call: Call<List<VocabularyItem>>, t: Throwable) { Toast.makeText(context, "请求失败:${t.message}", Toast.LENGTH_SHORT).show() } })
4. 适配LazyColumn数据源
因为data现在是列表类型,直接使用items(data.value)即可:
LazyColumn( contentPadding = PaddingValues( horizontal = 12.dp, /*vertical = 0.dp*/ ), verticalArrangement = Arrangement.spacedBy(10.dp) ) { items(data.value) { item -> Cards_Vocabulary(data = item, navController) //Divider(color = Color.Gray, thickness = 1.dp) } } // END LazyColumn
额外优化建议
给PHP接口添加参数缺失的处理逻辑,方便客户端调试:
if(!empty($_GET['Level']) && !empty($_GET['Unit'])) { // 现有查询逻辑... } else { echo json_encode(array("error" => "Level或Unit参数缺失")); }
内容的提问来源于stack exchange,提问作者Mohammed
相关产品推荐
相关产品推荐

