Hi, I'm working on an app to display weather using...
# android
m
Hi, I'm working on an app to display weather using openWeather API, retrofit and moshi. The last thing I need to do. It is to display weather information for each day. For this I need to create an adapter for listview. So I had an idea inside the onResponse method. Add individual elements to the array. But that doesn't work. Could someone advise me how to do this?
Copy code
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)



        val _status = MutableLiveData<String?>()

        val status: LiveData<String?> = _status
        val api : String = "33aa634c216259f797f35e862f0*****"

        val spinner = findViewById<Spinner>(R.id.cities)
        //val result = findViewById<TextView>(R.id.result)
        val cities = arrayOf("New York", "Sydney")
        val cnt = findViewById<EditText>(R.id.NumberOfDays)
        val button = findViewById<Button>(R.id.button)

        val arrayAdapter: ArrayAdapter<*>
        val data = arrayListOf<String>();
        var listView = findViewById<ListView>(R.id.list)
        arrayAdapter = ArrayAdapter(this, android.R.layout.simple_list_item_1, data)
        listView.adapter = arrayAdapter


        spinner.adapter = ArrayAdapter<String>(this, android.R.layout.simple_spinner_dropdown_item, cities)


        button.setOnClickListener {
            val selected = spinner.selectedItem as String

            var lat: String = ""
            var lon: String = ""
            if (selected == "New York") {
                lat = "40.79052384606425"
                lon = "-73.95908688800822"
            } else if (selected == "Sydney") {
                lat = "-33.8470241774331"
                lon = "151.0624326592654"
            }

            if(!TextUtils.isEmpty(cnt.text.toString())){
                lifecycleScope.launch{
                    WeatherApi.retrofitService.getWeatherData(lat, lon, api, "metric", cnt.text.toString()).enqueue(object: Callback<WeatherInfo> {
                        override fun onResponse(call: Call<WeatherInfo>, response: Response<WeatherInfo>) {
                            data.add(response.body()?.city?.name.toString())
                            //result.text = response.body().toString()
                            Log.d("Full response: ", response.body().toString())
                        }

                        override fun onFailure(call: Call<WeatherInfo>, t: Throwable) {
                            Log.d("Failure: ", t.message.toString())
                        }

                    })
                }
            }
        }

    }
}
😶 1
🧵 2
j
don't add to the array underlying the adapter, add to the adapter. This will automatically trigger the necessary datasetchanged observation.
But in general, have a look at RecyclerView (with ListAdapter) instead of ListView.
m
Okay, now I'm gonna be a jerk. I'll create the adapter when I finish declaring the data field. Still, everything in the onResponse method doesn't make it into the array, is this good?
Copy code
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        ...
        var data = arrayOf<String>()
        val arrayAdapter: ArrayAdapter<*>
        var listView = findViewById<ListView>(R.id.list)

        ....

            if(!TextUtils.isEmpty(cnt.text.toString())){
                lifecycleScope.launch{
                    WeatherApi.retrofitService.getWeatherData(lat, lon, api, "metric", cnt.text.toString()).enqueue(object: Callback<WeatherInfo> {
                        override fun onResponse(call: Call<WeatherInfo>, response: Response<WeatherInfo>) {
                            data += "five"
                            Log.d("Full response: ", response.body().toString())
                        }

                        override fun onFailure(call: Call<WeatherInfo>, t: Throwable) {
                            Log.d("Failure: ", t.message.toString())
                        }

                    })
                }
            }
        }

        arrayAdapter = ArrayAdapter(this, android.R.layout.simple_list_item_1, data)
        listView.adapter = arrayAdapter

    }
}
I will consider using recyclerView.
j
This won't work. And just switching to RecyclerView won't help you; you should really read up on the guides and docs for ListView/RecyclerView (they do share common concepts). But to give you some pointers on what to look for specifically so you'll see some progress:
• how can the ListView know that you added something to the underlying array (and it should now draw more items)? • when will the arrayAdapter be instantiated? • when will the ListView gets its adapter (datasource) set?
• when will you actually get your call response and add the item to the array?