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

Android中Kotlin使用Volley发起请求无响应问题求助

问题描述

我尝试通过RecyclerView动态创建CardView,再调用API接口获取数据填充TextView,但请求似乎未执行。此前手动创建TextView并填充数据的方式可以正常工作,但改用动态生成的CardView后无任何反应,恳请各位开发者提供指导。

目前可见Result1并未更新为请求响应,但在stringRequest外部使用jsonView.text = "something"可以修改内容。


相关代码

MainActivity代码

class MainActivity : AppCompatActivity() {
    //    private var message: TextView = findViewById<TextView>(R.id.jsonParse)

    lateinit var weatherRV: RecyclerView
    lateinit var weatherModelArray: ArrayList<WeatherViewModel>
    override fun onCreate(savedInstanceState: Bundle?) {

        super.onCreate(savedInstanceState)

        setContentView(R.layout.activity_main)
        supportActionBar?.hide()
        weatherRV = findViewById(R.id.mainView)

        weatherModelArray = ArrayList()


        val model1 = WeatherViewModel("Open weather", "")
        val model2 = WeatherViewModel("Yr.no", "")

        weatherModelArray.add(model1)
        weatherModelArray.add(model2)

        val weatherAdapter = WeatherAdapter(this, weatherModelArray)
        val linearLayoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)

        weatherRV.layoutManager = linearLayoutManager
        weatherRV.adapter = weatherAdapter

        apICall(this@MainActivity, model1)
    }

}

apiCall函数代码

@RequiresApi(Build.VERSION_CODES.O) 
internal fun apICall(context: Context, jsonView: WeatherViewModel) {
    var lat: Double? = null
    var lon: Double? = null
    var url: String? = null
    val apiKey: String = "XXXX"

    lat = YYY.Y
    lon = YYY.Y
    url = "https://api.openweathermap.org/data/2.5/onecall?lat=${lat}&lon=${lon}&appid=${apiKey}&units=metric&exclude=minutely,hourly"
    // Instantiate the RequestQueue.
    val queue = Volley.newRequestQueue(context)

    val gsonPretty = GsonBuilder().setPrettyPrinting().create() 
    // Request a string response from the provided URL.
    val stringRequest = StringRequest(
        Request.Method.GET, url,
        {response ->
            val gson = Gson()
            val openJSON = gson.fromJson(response.toString(), OpenWeatherJSON::class.java)
            val prettyJsonString = gsonPretty.toJson(openJSON)
            try {
                val dt = openJSON.daily[0].dt
                val sdf = SimpleDateFormat("dd-MM-yyyy")
                val date = Date(dt * 1000) //                snackbar.dismiss()

                sdf.format(date) //                jsonView.apiResult = sdf.format(date) //                jsonView.apiResult.append("
")
                jsonView.apiResult = openJSON.daily[0].temp.toString()
            }
            catch (e: Exception) {
                jsonView.apiResult = e.toString()
            }
        },
        {
            jsonView.apiResult = "Error"
        })

    // Add the request to the RequestQueue.
    queue.add(stringRequest) }

Update1:WeatherAdapter代码

class WeatherAdapter(context: Context, weatherModelArray: ArrayList<WeatherViewModel>):
    RecyclerView.Adapter<WeatherAdapter.ViewHolder>() {
    private val weatherModelArray: ArrayList<WeatherViewModel>

    // Constructor
    init {
        this.weatherModelArray = weatherModelArray
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): WeatherAdapter.ViewHolder {
        val view: View = LayoutInflater.from(parent.context).inflate(R.layout.card_layout, parent, false)
        return ViewHolder(view)
    }

    override fun onBindViewHolder(holder: WeatherAdapter.ViewHolder, position: Int) {
        val model = weatherModelArray[position]
        holder.apiName.text = model.apiName
        holder.apiResult.text = model.apiResult

    }

    override fun getItemCount(): Int {
        return weatherModelArray.size
    }

    inner class ViewHolder(itemView: View): RecyclerView.ViewHolder(itemView) {
        val apiName: TextView
        val apiResult: TextView

        init {
            apiName = itemView.findViewById(R.id.idApiName)
            apiResult = itemView.findViewById(R.id.idApiResult)
        }
    }
}

解决方案

问题核心:API请求其实已经执行了,但你修改WeatherViewModel的apiResult后,RecyclerView的Adapter没有收到数据变更通知,所以不会重新绑定数据刷新UI。

步骤1:修改MainActivity,保留Adapter引用

把Adapter从局部变量改成成员变量,方便后续调用刷新方法:

class MainActivity : AppCompatActivity() {
    lateinit var weatherRV: RecyclerView
    lateinit var weatherModelArray: ArrayList<WeatherViewModel>
    lateinit var weatherAdapter: WeatherAdapter // 改为成员变量

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        supportActionBar?.hide()
        weatherRV = findViewById(R.id.mainView)

        weatherModelArray = ArrayList()

        val model1 = WeatherViewModel("Open weather", "")
        val model2 = WeatherViewModel("Yr.no", "")

        weatherModelArray.add(model1)
        weatherModelArray.add(model2)

        weatherAdapter = WeatherAdapter(this, weatherModelArray) // 初始化成员变量
        val linearLayoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)

        weatherRV.layoutManager = linearLayoutManager
        weatherRV.adapter = weatherAdapter

        apICall(this@MainActivity, model1, 0) // 传入model在列表中的位置
    }
}

步骤2:修改apICall函数,更新数据后通知Adapter

在API回调中更新apiResult后,调用Adapter的notifyItemChanged方法刷新对应位置的UI:

@RequiresApi(Build.VERSION_CODES.O) 
internal fun apICall(context: Context, jsonView: WeatherViewModel, position: Int) {
    var lat: Double? = null
    var lon: Double? = null
    var url: String? = null
    val apiKey: String = "XXXX"

    lat = YYY.Y
    lon = YYY.Y
    url = "https://api.openweathermap.org/data/2.5/onecall?lat=${lat}&lon=${lon}&appid=${apiKey}&units=metric&exclude=minutely,hourly"
    val queue = Volley.newRequestQueue(context)

    val gsonPretty = GsonBuilder().setPrettyPrinting().create() 
    val stringRequest = StringRequest(
        Request.Method.GET, url,
        {response ->
            val gson = Gson()
            val openJSON = gson.fromJson(response.toString(), OpenWeatherJSON::class.java)
            try {
                val dt = openJSON.daily[0].dt
                val sdf = SimpleDateFormat("dd-MM-yyyy")
                val date = Date(dt * 1000)
                sdf.format(date)
                jsonView.apiResult = openJSON.daily[0].temp.toString()
                // 通知Adapter刷新对应位置
                (context as MainActivity).weatherAdapter.notifyItemChanged(position)
            }
            catch (e: Exception) {
                jsonView.apiResult = e.toString()
                (context as MainActivity).weatherAdapter.notifyItemChanged(position)
            }
        },
        {
            jsonView.apiResult = "Error"
            (context as MainActivity).weatherAdapter.notifyItemChanged(position)
        })

    queue.add(stringRequest) 
}

可选优化:给Adapter添加更新方法

可以在Adapter中封装一个更新单个item的方法,让代码更清晰:

class WeatherAdapter(context: Context, weatherModelArray: ArrayList<WeatherViewModel>):
    RecyclerView.Adapter<WeatherAdapter.ViewHolder>() {
    private val weatherModelArray: ArrayList<WeatherViewModel>

    init {
        this.weatherModelArray = weatherModelArray
    }

    // 添加单个item更新方法
    fun updateItem(position: Int) {
        notifyItemChanged(position)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): WeatherAdapter.ViewHolder {
        val view: View = LayoutInflater.from(parent.context).inflate(R.layout.card_layout, parent, false)
        return ViewHolder(view)
    }

    override fun onBindViewHolder(holder: WeatherAdapter.ViewHolder, position: Int) {
        val model = weatherModelArray[position]
        holder.apiName.text = model.apiName
        holder.apiResult.text = model.apiResult
    }

    override fun getItemCount(): Int {
        return weatherModelArray.size
    }

    inner class ViewHolder(itemView: View): RecyclerView.ViewHolder(itemView) {
        val apiName: TextView
        val apiResult: TextView

        init {
            apiName = itemView.findViewById(R.id.idApiName)
            apiResult = itemView.findViewById(R.id.idApiResult)
        }
    }
}

然后在apICall中调用:

(context as MainActivity).weatherAdapter.updateItem(position)

内容的提问来源于stack exchange,提问作者Jan Doležal

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 21:27:26