Jan Doležal
Jan Doležal

Reputation: 175

Kotlin not making request Volley - android

I am trying to "dynamically" create CardView and then fill TextView with data from an API call. The thing is, to me it seems like the request is not getting called.

I created an adapter class based on Create dynamically lists with RecyclerView which is working fine and I am adding as many windows as needed. And then in the MainActivity, I am trying to do an API request with Volley. Before I created manually TextView and fed the results manually into it - which worked fine. But now with this dynamically created CardView nothing is happening. Could anyone try to guide me please?

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("\n")
                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) }

Now in the image below you can see, that Result1 is not getting changed into the request response. I can change it with jsonView.text = "something" outside the stringRequest Result1 empty

Update1:

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)
        }
    }
}

Upvotes: 0

Views: 179

Answers (1)

Tyler V
Tyler V

Reputation: 10910

You need to notify the RecyclerView adapter that the data has changed after you change the data. This means calling notifyDataSetChanged from within the callback. That would look something like this:

internal fun apICall(context: Context, jsonView: WeatherViewModel, adapter: WeatherAdapter) {
    //...
    
    val stringRequest = StringRequest(
        Request.Method.GET, url,
        {response ->
            //...
            jsonView.apiResult = openJSON.daily[0].temp.toString()
            adapter.notifyDataSetChanged()
        },
        {
            jsonView.apiResult = "Error"
            adapter.notifyDataSetChanged()
        })

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

Upvotes: 1

Related Questions