Android Spinner's onItemSelected executed twice when going back to Fragment

android spinner style
android spinner adapter
android spinner mode
android spinner hint
android spinner custom adapter
android spinner github
android spinner material design
android spinner text color

I created a spinner for my Fragment that populates it with data retrieved from an HTTP callout. When the Fragment is first created, I populate the spinner with its selection choices, set its setOnItemSelectedListener and set its initial selection in onCreateView().

    stateSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {

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


            if (spinnerPosition != position)
            {
                spinnerPosition = position;
                TextView stateSelected = (TextView) view;
                String stateSelectedStr = stateSelected.getText().toString();


                LinearLayout ballotsDisplay = (LinearLayout) getActivity().findViewById(R.id.ballotsDisplay);
                ballotsDisplay.removeAllViews();

                Map<String, String> calloutParams = new HashMap<String, String>();
                calloutParams.put("state", stateSelectedStr);

                // Create and execute AsyncTask to retrieve ballots
                new RetrieveBallots().execute(calloutParams);
            }
        }

        public void onNothingSelected(AdapterView<?> parent) {
            return;
        }
    });

    // Set default selection for spinner
    int defaultState = adapter.getPosition(userState);

    if (defaultState == -1)
    {
        defaultState = 0;
    }

    stateSpinner.setSelection(defaultState);

When the Fragment is created, everything works well, the spinner position is set to its default and the spinner item is selected once as shown in the log below:

5009-5009/com.project.test D/TEST﹕ onCreateView called
5009-5009/com.project.test D/TEST﹕ stateSpinner.setSelection
5009-5009/com.project.test D/TEST﹕ onActivityCreated called
5009-5009/com.project.test D/TEST﹕ onResume called
5009-5009/com.project.test D/TEST﹕ spinner item selected

The problem occurs when I navigate away from the Fragment to another fragment (I store the fragment onto backstack). When I click back to go back to my original Fragment, the spinner seems to have its item selected twice:

5009-5009/com.project.test D/TEST﹕ onCreateView called
5009-5009/com.project.test D/TEST﹕ stateSpinner.setSelection
5009-5009/com.project.test D/TEST﹕ onActivityCreated called
5009-5009/com.project.test D/TEST﹕ onResume called
5009-5009/com.project.test D/TEST﹕ spinner item selected
5009-5009/com.project.test D/TEST﹕ spinner item selected

So I have 2 questions:

1) Why does the spinner register 2 item selection occurrences when returning to it from the Back button.

2) Is there a fix to prevent 2 item selections from occurring? Right now the fragment is being populated with duplicate data since it retrieves the data twice.

** EDIT ** After changing to stateSpinner.setSelection(defaultState, false), I would get a null Pointer exception at ballotsDisplay.removeAllViews(); seems like ballotsDisplay is set to null for some reason with that change

stacktrace:

05-15 07:25:48.303 6153-6153/com.poliseewriters.polisee E/AndroidRuntime﹕ FATAL EXCEPTION: main java.lang.NullPointerException at com.polisee.ballotmeasures.BallotMeasuresFragment$1.onItemSelected(BallotMeasuresFragment.java:287) at android.widget.AdapterView.fireOnSelected(AdapterView.java:882) at android.widget.AdapterView.selectionChanged(AdapterView.java:865) at android.widget.AdapterView.checkSelectionChanged(AdapterView.java:1017) at android.widget.Spinner.layout(Spinner.java:363) at android.widget.AbsSpinner.setSelectionInt(AbsSpinner.java:292) at android.widget.AbsSpinner.setSelection(AbsSpinner.java:269) at com.polisee.ballotmeasures.BallotMeasuresFragment.setStateSpinner(BallotMeasuresFragment.java:314) at com.polisee.ballotmeasures.BallotMeasuresFragment.onCreateView(BallotMeasuresFragment.java:201) at android.support.v4.app.Fragment.performCreateView(Fragment.java:1786) at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:953) at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1136) at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:739) at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1499) at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:456) at android.os.Handler.handleCallback(Handler.java:605) at android.os.Handler.dispatchMessage(Handler.java:92) at android.os.Looper.loop(Looper.java:137) at android.app.ActivityThread.main(ActivityThread.java:4441) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:511) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551) at dalvik.system.NativeStart.main(Native Method)

** EDIT: Updated code to prevent onItemSelected from executing twice, needed to add null check for ballotsDisplay **

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
    if (savedInstanceState != null) {
        Log.d("TEST", "bundle = " + savedInstanceState.toString());
    }

    Log.d("TEST", "onCreateView called");

    View view = (View) inflater.inflate(R.layout.fragment_ballot_measures, container, false);

    setStateSpinner(view);

    return view;
}


private void setStateSpinner(View view) {

    try {
        states = Utilities.getAllStateNames();
    }
    catch (Exception e) {
        Log.e("Error", "Error retrieving names: " + e.getMessage());
    }

    Spinner stateSpinner = (Spinner) view.findViewById(R.id.stateSpinner);

    final ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(), R.layout.ballotmeasures_state_spinner, states);
    adapter.setDropDownViewResource(R.layout.ballotmeasures_state_spinner_dropdown);

    stateSpinner.setAdapter(adapter);

    stateSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {

        // Callback method to invoke when a state has been selected
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id)
        {
            Log.d("TEST", "spinner item selected");

                TextView stateSelected = (TextView) view;
                String stateSelectedStr = stateSelected.getText().toString();

                // Remove all currently displayed views in the layout
                LinearLayout ballotsDisplay = (LinearLayout) getActivity().findViewById(R.id.ballotsDisplay);
                if (ballotsDisplay != null)
                {
                    ballotsDisplay.removeAllViews();
                }

                Map<String, String> calloutParams = new HashMap<String, String>();
                calloutParams.put("state", stateSelectedStr);

                // AsyncTask to execute data retrieval 
                new RetrieveBallots().execute(calloutParams);
            }

        public void onNothingSelected(AdapterView<?> parent) {
            return;
        }
    });

    // Set default selection for spinner
    int defaultState = adapter.getPosition(userState);

    if (defaultState == -1)
    {
        defaultState = 0;
    }

    Log.d("TEST", "stateSpinner.setSelection");
    stateSpinner.setSelection(defaultState, false);
}

Use stateSpinner.setSelection(defaultState, false); in place of stateSpinner.setSelection(defaultState);

Spinner, Android - Spinner - Spinner allows you to select an item from a drop down menu. val spinner: Spinner = findViewById (R.id.spinner) // Create an ArrayAdapter using the string array and a default spinner layout ArrayAdapter.createFromResource (this, R.array.planets_array, android.R.layout.simple_spinner_item).also { adapter -> // Specify the layout to use when the list of choices appears adapter.setDropDownViewResource (android.R.layout.simple_spinner_dropdown_item) // Apply the adapter to the spinner spinner.adapter = adapter }

The problem is the onItemSelected() callback gets called twice by Android Framework (maybe by design), the first time the view parameter is null, and the second time it is instantiated.

You cannot prevent 2 item selections from occurring, but you can check if the view variable is null, if not, do the rest things.

Android - Spinner, In this video we will create a simple spinner in Android Studio and fill it with a string array from Duration: 5:14 Posted: Nov 13, 2017 Android Spinner is like the combox box of AWT or Swing. It can be used to display the multiple options to the user in which only one item can be selected by the user. Android spinner is like the drop down menu with multiple values from which the end user can select only one value. Android spinner is associated with AdapterView.

Add condition view!=null in ItemSelectedListener like this:

spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
                    @Override
                    public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {

                        if(view!=null)
                        {//write your code
                        }
                    }

                    @Override
                    public void onNothingSelected(AdapterView<?> parent) {

                    }
                });

Text Spinner - Android Studio Tutorial, Android Spinner is like the combox box of AWT or Swing. It can be used to display the multiple options to the user in which only one item can be selected by the� In android, Spinner is a view that allows a user to select one value from the list of values. The spinner in android will behave same as a dropdown list in other programming languages.

Android Spinner Example, In Android, Spinner is used to select one value from a set of values. In the default state, a spinner shows its currently selected value. Touching the spinner displays � In android development, spinner widget gives us facility to create a drop down menu with multiple options. User can select any option from this drop down menu and we can track the selection of the user and can write logic with selected option. Spinner allows user to select only one value.

Android Spinner - drop down list, P.S This project is developed in Eclipse 3.7, and tested with Android 2.3.3. 1. List of Items in Spinner. Open “res/values/strings.xml” file, define the� In Android, Spinner provides a quick way to select one value from a set of values. Android spinners are nothing but the drop down-list seen in other programming languages. In a default state, a spinner shows its currently selected value. It provides a easy way to select a value from a list of values.

Android spinner (drop down list) example, Android Spinner is a view similar to the dropdown list which is used to select one option from the list of options. It provides an easy way to select� A spinner is a widget that have many options in dropdown, but only one option is displayed at a time. The displayed option is selected by the user. All the options in the spinner are provided using Adapter. Note – You must provide an adapter with the some options so that user can pick one among them.

Comments
  • I did what you said but now i get a nullpointerexception thrown at: LinearLayout ballotsDisplay = (LinearLayout) getActivity().findViewById(R.id.ballotsDisplay); ballotsDisplay.removeAllViews(); Any idea why this is happening now after using setSelection(...,false)?
  • Please check if ballotsDisplay is getting inflated properly. Seems like its null.
  • It does. If I switch it back to stateSpinner.setSelection(default), I don't receive that null pointer exception. Everything works fine, except for the double item selection when i hit back. I inflate the entire layout (ballotsDisplay is in it) before I set the spinner. Only when i change it to setSelection(default, false) does this exception occur
  • Can you please post your stacktrace.
  • what is the key difference between setSelection(int position) vs. setSelection(int position, boolean animate)? Looked through the Spinner documentation and the animate parameter isn't really explained.
  • For some reason when using a Spinner with an OnItemSelectedListener in Kotlin you can end up with some weird crashes, because of this issue and because using an OnItemSelectedListener as an anonymous class (instantiation directly on the setOnItemSelectedListener Android Studio didn't make the View nullable, which caused an exception on runtime, because Kotlin expected the View to be non-null, which it wasn't obviously. Thanks, you pointed me in the right direction :-)