Android development
Spinner
Programmatic selection
User interface
Mobile app development

Set selected item of spinner programmatically

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

Programmatically selecting a Spinner item is common when restoring user preferences, editing existing records, or reacting to data from another screen. The tricky part is timing: the adapter must be ready before selection, and the selection callback can fire even when the user did not tap anything. A robust implementation handles both concerns explicitly.

Basic Selection by Index

If your list is static and available on screen creation, you can set selection right after assigning the adapter. This is the simplest case and works well for fixed lists such as status values or simple options.

kotlin
1class BasicSpinnerActivity : AppCompatActivity() {
2    private lateinit var spinner: Spinner
3
4    override fun onCreate(savedInstanceState: Bundle?) {
5        super.onCreate(savedInstanceState)
6        setContentView(R.layout.activity_basic_spinner)
7
8        spinner = findViewById(R.id.prioritySpinner)
9
10        val items = listOf("Low", "Medium", "High")
11        val adapter = ArrayAdapter(this, android.R.layout.simple_spinner_item, items).apply {
12            setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
13        }
14
15        spinner.adapter = adapter
16
17        // Select "High" by index.
18        spinner.setSelection(2, false)
19    }
20}

Use the two-argument version setSelection(position, animate) when you want predictable UI behavior. Setting animate to false avoids unnecessary transition effects during initial screen load.

Selection by Value with Dynamic Data

In real apps, spinner data often comes from network or database calls. In that flow, you usually know a value, not an index, so you must find the matching position after data arrives.

kotlin
1data class Country(val code: String, val label: String) {
2    override fun toString(): String = label
3}
4
5class CountryActivity : AppCompatActivity() {
6    private lateinit var spinner: Spinner
7
8    override fun onCreate(savedInstanceState: Bundle?) {
9        super.onCreate(savedInstanceState)
10        setContentView(R.layout.activity_country)
11
12        spinner = findViewById(R.id.countrySpinner)
13
14        lifecycleScope.launch {
15            val countries = loadCountriesFromApi()
16            val adapter = ArrayAdapter(this@CountryActivity, android.R.layout.simple_spinner_item, countries)
17            adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
18            spinner.adapter = adapter
19
20            val savedCode = "CA"
21            val index = countries.indexOfFirst { it.code == savedCode }
22            if (index >= 0) {
23                spinner.setSelection(index, false)
24            }
25        }
26    }
27
28    private suspend fun loadCountriesFromApi(): List<Country> {
29        delay(150)
30        return listOf(
31            Country("US", "United States"),
32            Country("CA", "Canada"),
33            Country("MX", "Mexico")
34        )
35    }
36}

The key rule is simple: do not call setSelection before the adapter has data. If selection happens too early, Android silently keeps position zero, which looks like random behavior during testing.

Managing Listener Side Effects

onItemSelected can fire on first bind. If that callback triggers network requests or form recalculations, screen initialization can become noisy and expensive. A guard flag keeps startup clean.

kotlin
1class GuardedListenerActivity : AppCompatActivity() {
2    private var ignoreInitialSelection = true
3
4    override fun onCreate(savedInstanceState: Bundle?) {
5        super.onCreate(savedInstanceState)
6        setContentView(R.layout.activity_guarded_spinner)
7
8        val spinner: Spinner = findViewById(R.id.typeSpinner)
9        val values = listOf("Retail", "Wholesale", "Distributor")
10        val adapter = ArrayAdapter(this, android.R.layout.simple_spinner_item, values)
11        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
12        spinner.adapter = adapter
13
14        spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
15            override fun onItemSelected(parent: AdapterView<*>, view: View?, position: Int, id: Long) {
16                if (ignoreInitialSelection) {
17                    ignoreInitialSelection = false
18                    return
19                }
20
21                val selected = values[position]
22                Log.d("Spinner", "User selected: $selected")
23            }
24
25            override fun onNothingSelected(parent: AdapterView<*>) = Unit
26        }
27
28        spinner.setSelection(1, false)
29    }
30}

If you need Java in a legacy codebase, the same principles apply.

java
1Spinner spinner = findViewById(R.id.statusSpinner);
2List<String> statuses = Arrays.asList("Draft", "Review", "Published");
3ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, statuses);
4adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
5spinner.setAdapter(adapter);
6
7int index = statuses.indexOf("Review");
8if (index >= 0) {
9    spinner.setSelection(index, false);
10}

Common Pitfalls

  • Calling setSelection before adapter data is loaded. Fix by setting selection only after adapter assignment and data readiness.
  • Assuming selection callback means user action. Fix by guarding the initial callback when screen setup should not trigger business logic.
  • Selecting by index from stale assumptions. Fix by selecting by value when data can be reordered or filtered.
  • Not handling missing values. Fix by checking index result and defining a fallback option.
  • Losing state on rotation. Fix by storing selected key in ViewModel or saved state and reapplying after data load.

Summary

  • Programmatic Spinner selection is reliable when timing and callbacks are handled intentionally.
  • Use index-based selection for static lists and value-based selection for dynamic lists.
  • Set selection only after adapter data is available.
  • Guard onItemSelected during startup if initialization should be side-effect free.
  • Persist the selected key and reapply it after configuration changes.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.