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

Kotlin+Retrofit实现SearchView搜索时数据与查询不匹配问题

问题描述

在Android项目中,使用Kotlin结合Retrofit实现SearchView搜索功能时,虽能获取到JSON响应,但返回的数据与输入的查询关键词不匹配。

核心问题与修复方案

1. Retrofit搜索接口定义错误

原接口手动拼接了search=参数,且@Query的参数名为空,导致请求URL格式错误,后端无法正确接收搜索关键词。

修复后的接口代码:

@Headers("Accept: application/json")
@GET("markets") // 移除手动拼接的search参数
suspend fun searchItems(
    @Header("Authorization") bearerToken: String,
    @Query("search") keyword: String // 指定正确的参数名"search"
): Response<MarketAccessResponse>

2. 适配器未正确更新数据源

原setItems方法未替换内部数据源,仅调用notifyDataSetChanged,导致RecyclerView始终显示旧数据。

修复后的适配器代码:

// 将items改为可变列表
class MarketItemAdapter(private val items: MutableList<Market> = mutableListOf())
    : RecyclerView.Adapter<MarketItemAdapter.ViewHolder>() {

    // ... 其他代码保持不变

    fun setItems(newItems: List<Market>) {
        items.clear()
        items.addAll(newItems)
        notifyDataSetChanged()
    }
}

3. 数据模型泛型缺失

MarketAccessResponse的data字段仅声明为List,未指定泛型List<Market>,可能导致解析时无法正确映射数据。

修复后的MarketAccessResponse:

data class MarketAccessResponse(
    val data: List<Market>, // 指定泛型为Market
    val message: String,
    val error: Boolean
)

4. Activity中适配器状态混乱

原代码初始化adapter后,getMarketAccess又新建适配器实例设置给RecyclerView,导致搜索时更新的是未关联的旧适配器。

修复后的Activity代码:

class MarketAccessActivity : AppCompatActivity() {

    private lateinit var ivBack : ImageView
    private lateinit var rvMarket: RecyclerView
    private lateinit var adapter: MarketItemAdapter
    private lateinit var searchView: SearchView

    @SuppressLint("MissingInflatedId")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_market_access)

        ivBack = findViewById(R.id.iv_back)
        ivBack.setOnClickListener {
            startActivity(Intent(this@MarketAccessActivity, HomeActivity::class.java))
            finish()
        }

        searchView = findViewById(R.id.searchView)
        adapter = MarketItemAdapter()
        rvMarket = findViewById(R.id.rv_market_access)
        val layoutManager = GridLayoutManager(this, 2)
        rvMarket.layoutManager = layoutManager
        rvMarket.adapter = adapter // 提前绑定适配器
        getMarketAccess()

        searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
            override fun onQueryTextSubmit(query: String): Boolean {
                return false
            }

            override fun onQueryTextChange(newText: String): Boolean {
                searchItems(newText)
                return false
            }
        })
    }

    private fun searchItems(keyword: String) {
        val (savedToken, savedRefreshToken) = SharedPrefsUtil.getTokens(this@MarketAccessActivity)
        if (savedToken != null && savedRefreshToken != null) {
            CoroutineScope(Dispatchers.IO).launch {
                val apiService = ApiClient.apiService.searchItems("Bearer $savedToken",keyword)
                try {
                    if (apiService.isSuccessful) {
                        val items = apiService.body()?.data
                        runOnUiThread {
                            adapter.setItems(items.orEmpty())
                        }
                        Log.d("data-search", apiService.body().toString() )
                    }
                } catch (e: Exception) {
                    e.printStackTrace()
                    Log.d("$e", keyword )
                }
            }
        }
    }

    private fun getMarketAccess() {
        val (savedToken, savedRefreshToken) = SharedPrefsUtil.getTokens(this@MarketAccessActivity)
        if (savedToken != null && savedRefreshToken != null) {

            val progressDialog = ProgressDialog(this@MarketAccessActivity)
            progressDialog.setMessage("Loading data...")
            progressDialog.setCancelable(false)
            progressDialog.show()

            val call = ApiClient.apiService.getMarketList("Bearer $savedToken")
            call.enqueue(object : Callback<MarketAccessResponse> {
                override fun onResponse(call: Call<MarketAccessResponse>, response: Response<MarketAccessResponse>) {
                    progressDialog.dismiss()

                    if (response.isSuccessful) {
                        val marketResponse = response.body()
                        marketResponse?.let {
                            val marketList = marketResponse.data
                            adapter.setItems(marketList) // 使用已初始化的适配器更新数据
                            Log.d("data-muncul",response.body()?.data.toString())
                        }
                    } else {
                        Toast.makeText(this@MarketAccessActivity,
                            "Failed to fetch markets", Toast.LENGTH_SHORT).show()
                        Log.e("failed", "Failed fetch data")
                    }
                }

                override fun onFailure(call: Call<MarketAccessResponse>, t: Throwable) {
                    progressDialog.dismiss()
                    Toast.makeText(this@MarketAccessActivity,
                        "Failed to fetch lands", Toast.LENGTH_SHORT).show()
                    Log.e("GetMarketsError", t.toString())
                }
            })
        }
    }
}

内容的提问来源于stack exchange,提问作者rifqi padi siliwangi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 20:14:58