Android Spinner
Item Selection
Event Handling
Java Programming
User Interface

Android Spinner Get the selected item change event

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

In Android, a Spinner reports selection changes through AdapterView.OnItemSelectedListener. The main wrinkle is that onItemSelected can fire during initial setup, so production code often needs to distinguish between the first automatic callback and a genuine user-triggered change.

Set Up The Spinner With An Adapter

A spinner needs an adapter that provides the display values:

java
1Spinner spinner = findViewById(R.id.categorySpinner);
2
3ArrayAdapter<String> adapter = new ArrayAdapter<>(
4        this,
5        android.R.layout.simple_spinner_item,
6        Arrays.asList("Books", "Movies", "Music")
7);
8
9adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
10spinner.setAdapter(adapter);

Once the adapter is attached, the widget knows what items it can show and select.

Listen For Selection Changes

The standard way to react to changes is setOnItemSelectedListener:

java
1spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
2    @Override
3    public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
4        String selected = parent.getItemAtPosition(position).toString();
5        Toast.makeText(parent.getContext(), "Selected: " + selected, Toast.LENGTH_SHORT).show();
6    }
7
8    @Override
9    public void onNothingSelected(AdapterView<?> parent) {
10        // Usually no action needed.
11    }
12});

Inside onItemSelected, you can use:

  • 'position for the numeric index'
  • 'id for the row id supplied by the adapter'
  • 'parent.getItemAtPosition(position) for the selected value'

That callback is the spinner equivalent of a selection-change event.

Handle The Initial Callback Carefully

Many developers are surprised that onItemSelected may run as soon as the spinner is initialized, before the user taps anything. If you only want user-driven changes, add a guard:

java
1final boolean[] initialized = {false};
2
3spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
4    @Override
5    public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
6        if (!initialized[0]) {
7            initialized[0] = true;
8            return;
9        }
10
11        String selected = parent.getItemAtPosition(position).toString();
12        Log.d("SpinnerDemo", "User changed selection to " + selected);
13    }
14
15    @Override
16    public void onNothingSelected(AdapterView<?> parent) {
17    }
18});

This is a pragmatic fix for screens where the default value should not immediately trigger filtering, network calls, or form updates.

Use Stronger Models For Real Data

For quick demos, strings are fine. In real apps, spinner items often represent objects:

java
1public class Category {
2    private final int id;
3    private final String label;
4
5    public Category(int id, String label) {
6        this.id = id;
7        this.label = label;
8    }
9
10    public int getId() {
11        return id;
12    }
13
14    @Override
15    public String toString() {
16        return label;
17    }
18}

Because ArrayAdapter uses toString() for display, this lets you keep both a human-readable label and an internal id:

java
Category selected = (Category) parent.getItemAtPosition(position);
int categoryId = selected.getId();

That pattern is safer than trying to map spinner positions back to database ids manually.

Persist Selection Across Recreation

If the screen is recreated, for example after rotation, restore the selected position so the UI stays consistent:

java
outState.putInt("selected_position", spinner.getSelectedItemPosition());

And later:

java
int position = savedInstanceState.getInt("selected_position", 0);
spinner.setSelection(position);

That matters because selection-driven forms can feel broken if the spinner silently resets.

If the spinner controls other UI sections, consider centralizing the selection handling in one method instead of duplicating logic inside the listener. That keeps the initialization path and the user-change path consistent.

Common Pitfalls

One common mistake is assuming onItemSelected only fires after a user click. It often fires during initialization too.

Another issue is reading the wrong value from the adapter and treating the integer position as the business id.

A third problem is modifying the spinner dataset and forgetting to notify the adapter, which makes the visible list and internal data drift apart.

Finally, when form logic depends on selection, developers sometimes trigger expensive work from every callback without guarding against duplicate initial calls.

Summary

  • Use setOnItemSelectedListener to react to spinner selection changes.
  • Read the selected value with getItemAtPosition(position).
  • Expect one callback during initial setup unless you guard against it.
  • Prefer real model objects over raw strings when the selection maps to ids or records.
  • Save and restore the selected position when screen recreation matters.

Course illustration
Course illustration