La richiamata onItemScreen di Spinner chiamata due volte dopo una rotazione se è selezionata la posizione diversa da zero

Quando creo la mia attività, creo un Spinner, assegnandolo come listener e un valore iniziale. So che la chiamata onItemSelected viene chiamata automaticamente durante l'initialization dell'applicazione. Quello che mi sembra strano è che questo accade due volte quando il dispositivo è ruotato, causando alcuni problemi che dovrò aggirare un po '. Ciò non avviene se la selezione iniziale dello spinner è zero. Sono stato in grado di isolare il problema, ecco l'triggerszione più semplice che lo spinge:

 public class MainActivity extends Activity implements OnItemSelectedListener { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.i("Test","Activity onCreate"); setContentView(R.layout.activity_main); ((Spinner)findViewById(R.id.spinner1)).setSelection(2); ((Spinner)findViewById(R.id.spinner1)).setOnItemSelectedListener(this); } @Override public void onItemSelected(AdapterView<?> spin, View selview, int pos, long selId) { Log.i("Test","spin:"+spin+" sel:"+selview+" pos:"+pos+" selId:"+selId); } @Override public void onNothingSelected(AdapterView<?> arg0) {} } 

Ecco il logcat visualizzato quando l'applicazione è stata avviata e poi il dispositivo è ruotato:

  • come icmp ping su android
  • estrarre l'asse, il passo e il rotolo da una matrix di rotazione
  • Lettura di un file PDF utilizzando la libreria iText
  • Come posso get un Uri ad un'image nella mia attività che funziona per la colonna SearchManager.SUGGEST_COLUMN_ICON_1?
  • Differenze di dependencies di Gradle tra compilazione, progetto apk, progetto di compilazione, fornito, progetto di implementazione
  • Come può un button get l'attenzione?
  •   I/Test( 9881): spin:android.widget.Spinner@4052f508 sel:android.widget.TextView@40530b08 pos:2 selId:2 I/Test( 9881): Activity onCreate I/Test( 9881): spin:android.widget.Spinner@40535d80 sel:android.widget.TextView@40538758 pos:2 selId:2 I/Test( 9881): spin:android.widget.Spinner@40535d80 sel:android.widget.TextView@40538758 pos:2 selId:2 

    È questo il comportmento previsto? Mi sto perdendo qualcosa?

  • Audio streaming da un URL in Android utilizzando MediaPlayer?
  • android: windowNoTitle non nasconde la barra di azione con appcompat-v7 21.0.0
  • Attività di Android sopra lo schermo di block predefinito
  • Alternative a google maps api
  • Mostra la tastiera software senza EditText
  • get la posizione corrente
  • 7 Solutions collect form web for “La richiamata onItemScreen di Spinner chiamata due volte dopo una rotazione se è selezionata la posizione diversa da zero”

    Gestito per trovare una soluzione in un'altra domanda di stackoverflow:

     spinner.post(new Runnable() { public void run() { spinner.setOnItemSelectedListener(listener); } }); 

    In generale, sembra che ci siano molti events che innescano la chiamata onItemSelected, ed è difficile tenere traccia di tutti. Questa soluzione consente di rispondere solo alle modifiche avviate dall'utente utilizzando un OnTouchListener.

    Crea il tuo ascoltatore per il filatore:

     public class SpinnerInteractionListener implements AdapterView.OnItemSelectedListener, View.OnTouchListener { boolean userSelect = false; @Override public boolean onTouch(View v, MotionEvent event) { userSelect = true; return false; } @Override public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) { if (userSelect) { // Your selection handling code here userSelect = false; } } } 

    Aggiungere l'ascoltatore alla filatrice come un OnItemSelectedListener e un OnTouchListener:

     SpinnerInteractionListener listener = new SpinnerInteractionListener(); mSpinnerView.setOnTouchListener(listener); mSpinnerView.setOnItemSelectedListener(listener); 

    Questo è ciò che ho fatto:

    Fare una variabile locale

     Boolean changeSpinner = true; 

    Sul saveInstanceMethod salvare la posizione di articolo selezionata del filatore

     @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putInt("ItemSelect",mySpinner.getSelectedItemPosition()); } 

    Quindi sull'attività creata ottiene che int da savedInstanceState e se l'int è! = 0, quindi impostare la variabile booleana su false;

     @Override public void onActivityCreated(Bundle savedInstanceState) { if (savedInstanceState!=null) { if (savedInstanceState.getInt("ItemSelect")!=0) { changeSpinner = false; } } } 

    E per ultimo sull'OnTemSelezionato dal filatore fanno questo

     mySpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { public void onItemSelected(AdapterView<?> parent,android.view.View v, int position, long id) { if (changeSpinner) { [...] } else { changeSpinner= true; } }); 

    Così, la prima volta quando viene chiamata non farà nulla, basta fare la variabile booleana vera e la seconda volta esegue il codice. Forse non la soluzione migliore ma funziona.

    Basta usare setSelection (#, false) prima di impostare l'ascoltatore:

     @Override protected void onCreate(Bundle savedInstanceState) { ... spinner.setSelection(2, false); spinner.setOnItemSelectedListener(this); } 

    La chiave è il secondo parametro che dice di non animare la transizione, eseguendo immediatamente l'azione e quindi impedendo che l'onItemSelected venga sparato due volte quando viene chiamato in onCreate.

    Prova questo:

     boolean mConfigChange = false; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub mConfigChange = false; super.onCreate(savedInstanceState); setContentView(R.layout.activity_mainf); Log.i("SpinnerTest", "Activity onCreate"); ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this, R.arrays.colors, android.R.layout.simple_spinner_item); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); ((Spinner) findViewById(R.id.spin)).setAdapter(adapter); ((Spinner) findViewById(R.id.spin)).setSelection(2); ((Spinner) findViewById(R.id.spin)).setOnItemSelectedListener(this); } @Override protected void onResume() { mConfigChange = true; super.onResume(); } @Override public void onItemSelected(AdapterView<?> spin, View selview, int pos, long selId) { if (!mConfigChange) Log.i("Test", "spin:" + spin + " sel:" + selview + " pos:" + pos + " selId:" + selId); else mConfigChange = false; } 

    Puoi call solo per setSelection una volta che conoscete l'elenco degli elementi e la posizione da select, in questo modo si evita di essere chiamato due volte per essere selezionato.

    Ho creato un articolo su quello che penso sia un approccio migliore Come evitare che onItemSelected sia chiamato due volte in Spinners

    La prima volta che onItemSelected eseguita l' onItemSelected , la view non è ancora gonfiata. La seconda volta è già gonfiato. La soluzione è quella di avvolgere methods all'interno di onItemSelected con if (view != null) .

     @Override public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) { if (view != null) { //do things here } } 
    L'Android è un fan Android di Google, tutto su telefoni Android, Android Wear, Android Dev e applicazioni Android Games e così via.