How to retrieve the value of a variable modified in the onItemSelected function with Kotlin in Android Studio?

212 Views Asked by At

I need to retrieve the value of a variable modified in the onItemSelected function using a when. Here is what I've done :

    (...)

    private var i: Int = 0

    override fun onCreate(savedInstanceState: Bundle?) {
        (...)

        categorySpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
            @SuppressLint("SetTextI18n")
            override fun onNothingSelected(parent: AdapterView<*>?) {

            }

            override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
                category = categories[position]

                when (category) {
                    "Décès" -> i = 1
                    "Habitat" -> i = 2
                }
            }
        }

        binding.tvtest.text = i.toString()

        val acteSpinner: Spinner = binding.acteCreatingSpinnerActes
        when (i) {
            1 -> {
                val adapter = ArrayAdapter(this, android.R.layout.simple_spinner_item, actes[actes.indexOf(deces)])
                adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
                acteSpinner.adapter = adapter
                acte = acteSpinner.selectedItem.toString()
            }
            2 -> {
                val adapter = ArrayAdapter(this, android.R.layout.simple_spinner_item, actes[actes.indexOf(habitat)])
                adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
                acteSpinner.adapter = adapter
                acte = acteSpinner.selectedItem.toString()
            }
        }
    }
}

I've tried to retrieve the value of variable I in a layout and I got i = 0.
I want to get the value obtained in the onItemSelected function

3

There are 3 best solutions below

0
jeremex On BEST ANSWER

Try this

override fun onCreate(savedInstanceState: Bundle?) {

    categorySpinner.onItemSelectedListener = object : ItemSelected{
                    override fun onItemSelected(parent: AdapterView<*>?,   view: View?, position: Int, id: Long) {
            category = categories[position]

            when (category) {
                "Décès" ->  getItemSelected(1)
                "Habitat" ->  getItemSelected(2)
            }}}
}

private fun setDataSpinner(i: Int,actes: Actes){
    binding.tvtest.text = i.toString()
    val acteSpinner: Spinner = binding.acteCreatingSpinnerActes

    val adapter = ArrayAdapter(this, R.layout.simple_spinner_item, actes)
    adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
    acteSpinner.adapter = adapter
    acte = acteSpinner.selectedItem.toString()
}

private fun getItemSelected(item: Int){
    when(item){
        1 -> { setDataSpinner(item,actes[actes.indexOf(deces)]) }
        2 -> { setDataSpinner(item,actes[actes.indexOf(habitat)]) }
    }
}


interface ItemSelected: AdapterView.OnItemSelectedListener {
    override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long)
    override fun onNothingSelected(parent: AdapterView<*>?) {}
}
1
Phuong On
  1. Should not use hard-string in code: "Décès", "Habitat"
  2. No need i variable. Just using position:
when (position) {
        0 -> {
            val adapter = ArrayAdapter(this, android.R.layout.simple_spinner_item, actes[actes.indexOf(deces)])
            adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
            acteSpinner.adapter = adapter
            acte = acteSpinner.selectedItem.toString()
        }
        1 -> {
            val adapter = ArrayAdapter(this, android.R.layout.simple_spinner_item, actes[actes.indexOf(habitat)])
            adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
            acteSpinner.adapter = adapter
            acte = acteSpinner.selectedItem.toString()
        } }
7
Tyler V On

There is no problem with changing a class member inside the callback, but your code as-written doesn't work because the callback doesn't run immediately - it runs later when the user clicks on an item.

It appears you want the adapter for acteSpinner to change between two different sets of data when you select something in categorySpinner. You can do that by modifying the data in the adapter directly. Here's an example of how you could do that.

// You could make adapter a class member, but it is not necessary
// for this example
//private lateinit var adapter: ArrayAdapter<String>

override fun onCreate(savedInstanceState: Bundle?) {
    //...
    
    val binding = ...
    
    val adapter = ArrayAdapter(this, android.R.layout.simple_spinner_item)
    adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
    acteSpinner.adapter = adapter
    
    // Initially set the adapter to show list one
    adapter.addAll(firstList)
    binding.tvtest.text = "List One"
    
    categorySpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
        @SuppressLint("SetTextI18n")
        override fun onNothingSelected(parent: AdapterView<*>?) {

        }

        override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
            category = categories[position]
            // POINT B - Inside the callback. This code does not
            // run immediately, it runs later when an 
            // item is selected

            when (category) {
                "Décès" -> {
                    adapter.clear()
                    adapter.addAll(decesArray)
                    adapter.notifyDataSetChanged()
                    binding.tvtest.text = "Décès"
                    println("TEST: added deces ${decesArray.contentToString()}")
                }
                "Habitat" -> {
                    adapter.clear()
                    adapter.addAll(habitatArray)
                    adapter.notifyDataSetChanged()
                    binding.tvtest.text = "Habitat"
                    println("TEST: added habitat ${habitatArray.contentToString()}")
                }
            }
        }
    }

    // POINT A - Outside the callback
    //...
}

Note the "Point A" and "Point B" comments - in this code "Point A" will run first, even though "Point B" is on an earlier line. If you try to do something at "Point A" using a variable you modified at "Point B" it will not work.