title: Android Spinner data view not updating on item re-selected
body: <p>I'm trying to customize a Spinner to be multi-selectable.  I have successfully made it multi-selectable, but when an item is reselected, the view inside of the spinner does not get updated.</p>
  
  <h1>The Problem</h1>
  
  <p>When an item is reselected in the <code>Spinner</code>, the <code>getView()</code> of my <code>SpinnerAdapter</code> gets called, produces the <code>View</code> that I want it to, but that <code>View</code> somehow does not get displayed.  I have stepped through everything in the debugger and I cannot find any differences between when a different item is selected or the same item is reselected.  I have been through all of the code in <code>Spinner</code> <code>AbsSpinner</code> and <code>AdapterView</code> and I cannot find what may be causing this.</p>
  
  <h1>For Example</h1>
  
  <p>The spinner is populated with 6 items: Choice 1-6.  The spinner originates with all items unselected.  <b>Choice 1, 2, and 4 are selected</b>.  The view inside the spinner displays "Choice 1, Choice 2, Choice 4" correctly.</p>
  
  <p><img src="https://i.imgur.com/FUgtzWy.png" width="200" height="225"/></p>
  
  <p><b>Choice 4 is unselected</b> (reselection as far as the Spinner is concerned).  Choice 4 is correctly unchecked from the list, but the view inside the spinner does not update.  <b>It still displays "Choice 1, Choice 2, Choice 4"</b>.  Stepping through the debugger, getView() on my SpinnerAdapter gets called and everything.  For some reason, the View doesn't actually get displayed.</p>
  
  <p><img src="https://i.imgur.com/DXEzWu2.png" width="200" height="225"/></p>
  
  <p><b>Choice 2 is unselected</b> (this is not a "re-selection" to the Spinner).  Here everything functions as expected.  Both the list items and the view inside the Spinner are updated.</p>
  
  <p><img src="https://i.imgur.com/ssQGdia.png" width="200" height="225"/></p>
  
  <h1>Some Code</h1>
  
  <h3>The multi-selectable Spinner</h3>
  
  <pre><code>public class MultiSelectSpinner extends Spinner {
  
      private OnItemSelectedListener listener;
  
      public MultiSelectSpinner(Context context) {
  
          super( context );
      }
  
      public MultiSelectSpinner(Context context, AttributeSet attrs) {
  
          super( context, attrs );
      }
  
      public MultiSelectSpinner(Context context, AttributeSet attrs, int defStyle) {
  
          super( context, attrs, defStyle );
      }
  
      @Override
      public void setSelection( int position ) {
  
          super.setSelection( position );
          if ( listener != null ) {
  
              listener.onItemSelected( this, getSelectedView(), position, getAdapter().getItemId( position ) );
          }
      }
  
      public void setOnItemSelectedEvenIfUnchangedListener( OnItemSelectedListener listener ) {
  
          this.listener = listener;
      }
  }
  </code></pre>
  
  <h3>Spinner Adapter</h3>
  
  <p>Only posting the important pieces here.  Leaving out getters/setters, etc.</p>
  
  <pre><code>public class FormChoiceSpinnerAdapter implements SpinnerAdapter, OnItemSelectedListener {
  
      private Choice[] choices;
      private String title;
      private final DataSetObservable dataSetObservable = new DataSetObservable();
  
      public FormChoiceSpinnerAdapter(String[] choices, String title) {
  
          setChoices( new Choice[choices.length] );
          for (int i = 0; i &lt; choices.length; i++) {
  
              getChoices()[i] = new Choice( choices[i] );
          }
      }
  
      @Override
      public View getView( int position, View convertView, ViewGroup parent ) {
  
          Context context = parent.getContext();
          if ( convertView == null ) {
  
              convertView = LayoutInflater.from( context ).inflate( android.R.layout.simple_spinner_item, parent, false );
          }
  
          String displayString = "";
  
          for (int i = 0; i &lt; getChoices().length; i++) {
  
              Choice choice = getChoices()[i];
  
              if ( choice.isSelected() ) {
  
                  displayString += choice.getLabel() + ", ";
              }
          }
  
          if ( displayString.length() &gt; 0 ) {
  
              displayString = displayString.trim().substring( 0, displayString.length() - 2 );
          }
          else {
  
              displayString = getTitle() + "...";
          }
  
          ( (TextView) convertView ).setText( displayString );
  
          return convertView;
      }
  
      @Override
      public View getDropDownView( int position, View convertView, ViewGroup parent ) {
  
          Context context = parent.getContext();
          if ( convertView == null ) {
  
              convertView = LayoutInflater.from( context ).inflate( R.layout.simple_dropdown_item, parent, false );
          }
  
          Choice choice = getChoices()[position];
          TextView text = (TextView) convertView.findViewById( android.R.id.text1 );
          text.setText( choice.getLabel() );
  
          ImageView selectedImage = (ImageView) convertView.findViewById( R.id.image_selected );
          int visibility = choice.isSelected() ? View.VISIBLE : View.GONE;
          selectedImage.setVisibility( visibility );
  
          return convertView;
      }
  
      @Override
      public void onItemSelected( AdapterView&lt;?&gt; parent, View view, int position, long id ) {
  
          Choice choice = getChoices()[position];
  
          choice.setSelected( !choice.isSelected() );
  
          ImageView imageView = (ImageView) view.findViewById( R.id.image_selected );
  
          if ( imageView != null ) {
              imageView.setVisibility( choice.isSelected() ? View.VISIBLE : View.GONE );
          }    
      }
  
      @Override
      public void onNothingSelected( AdapterView&lt;?&gt; parent ) {
  
          //No op
      }
  
      public static class Choice {
  
          private boolean selected;
          private String label;
  
          public Choice(String label) {
  
              this.label = label;
              selected = false;
          }
      }
  }
  </code></pre>