Spinner onItemSelected() executes inappropriately [duplicate]

David, here is a tutorial I wrote up for this problem...

Problem Statement

an undesirable onItemSelected() is triggered whilst the Gallery (or Spinner) is initializing. This means that code is prematurely executed; code which is intended to execute ONLY when a user physically makes a selection.

Solution

  1. in onCreate(), count how many Gallery (or Spinner) widgets you have in the view. (mGalleryCount)
  2. in onItemSelected(), count how often it has triggered. (mGalleryInitializedCount)
  3. when (mGalleryInitializedCount < mGalleryCount) == false, then execute the code meant for the user

Code Example

public class myActivity extends Activity implements OnItemSelectedListener
{
    //this counts how many Gallery's are on the UI
    private int mGalleryCount=0;

    //this counts how many Gallery's have been initialized
    private int mGalleryInitializedCount=0;

    //UI reference
    private Gallery mGallery;


    @Override
    public void onCreate(Bundle savedInstanceState)
    {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.myxmllayout);

        //get references to UI components
        mGallery = (Gallery) findViewById(R.id.mygallery);

        //trap selection events from gallery
        mGallery.setOnItemSelectedListener(this);

        //trap only selection when no flinging is taking place
        mGallery.setCallbackDuringFling(false);

        //
        //do other stuff like load images, setAdapter(), etc
        //

        //define how many Gallery's are in this view
        //note: this could be counted dynamically if you are programmatically creating the view
        mGalleryCount=1;

    }


    public void onItemSelected(AdapterView<?> parent, View view, int position, long id)
    {

        if (mGalleryInitializedCount < mGalleryCount)
        {
            mGalleryInitializedCount++;
        }
        else
        {
            //only detect selection events that are not done whilst initializing
            Log.i(TAG, "selected item position = " + String.valueOf(position) );
        }

    }

}

Why this works

this solution works because the Gallery finishes initialization long before a user is physically able to make a selection.


Here is a modified version of "Someone Somewhere" code. You can use it if you have a single view.

public class myActivity extends Activity implements OnItemSelectedListener
{
// Set view initialization to false while the it is being built
private boolean initializedView = false;

//UI reference
private Gallery mGallery;


@Override
public void onCreate(Bundle savedInstanceState)
{

    super.onCreate(savedInstanceState);
    setContentView(R.layout.myxmllayout);

    //get references to UI components
    mGallery = (Gallery) findViewById(R.id.mygallery);

    //trap selection events from gallery
    mGallery.setOnItemSelectedListener(this);

    //trap only selection when no flinging is taking place
    mGallery.setCallbackDuringFling(false);

    //
    //do other stuff like load images, setAdapter(), etc
    //


}


public void onItemSelected(AdapterView<?> parent, View view, int position, long id)
{

    if (initializedView ==  false)
    {
        initializedView = true;
    }
    else
    {
        //only detect selection events that are not done whilst initializing
        Log.i(TAG, "selected item position = " + String.valueOf(position) );
    }

}
}

Same solution:

private int m_intSpinnerInitiCount = 0;
private static final int NO_OF_EVENTS = 1;

...

m_spnTemplates.setOnItemSelectedListener(new Spinner.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parentView, 
                    View selectedItemView, int position, long id) { 

                //trying to avoid undesired spinner selection changed event, a known problem
                    if (m_intSpinnerInitiCount < NO_OF_EVENTS) {
                        m_intSpinnerInitiCount++;
                    } else {                
                        //YOUR CODE HERE
                    }                           
            }

I ran into this problem yesterday with an OnCheckedChangedListener. I ended up adding a boolean instance variable initialized to true inside of my adapter class with an accessor method isListenerEnabled(). I then set the variable to false in my layout code and set it to true again at the end of the layout code. In my listener, I inspect the value of the variable to decide whether to execute the listener code or not.