2012-03-20 20 views
6

Sto imparando come utilizzare i thread in Android, e per farlo ho creato una piccola applicazione che riproduce una serie di note. L'idea è che ci sia un pulsante di avvio e un pulsante di fine e che (ovviamente) se si preme il pulsante di avvio inizia a riprodurre musica, e se si preme il pulsante di fine, si ferma. Il pulsante di avvio funziona bene, ma il problema è che il pulsante di chiusura non lo fa. Sto avendo problemi a capire perché, quindi forse qualcuno di voi può aiutarmi. Questo è il codice:Il thread non si interrompe

public class PressAndPlay extends Activity { 
    private volatile Thread initBkgdThread; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 

     Button startButton = (Button) findViewById(R.id.trigger); 
     startButton.setOnClickListener(new View.OnClickListener() { 
      public void onClick(View view) { 

       // create thread 
       initBkgdThread = new Thread(new Runnable() { 
        public void run() { 
         play_music(); 
        } 
       }); 
       initBkgdThread.start(); 
      } 
     }); 

     Button endButton = (Button) findViewById(R.id.end); 
     endButton.setOnClickListener(new View.OnClickListener() { 
      public void onClick(View view) { 
       end_music(); 
      } 
     }); 
    } 

    int[] notes = {R.raw.c5, R.raw.b4, R.raw.a4, R.raw.g4}; 
    int NOTE_DURATION = 400; 
    MediaPlayer m_mediaPlayer; 

    private void play_music() { 
     for(int ii=0; ii<12; ii++) { 
      //check to ensure main activity is not paused 
      if(!paused) { 
       if (m_mediaPlayer != null) {m_mediaPlayer.release();} 
       m_mediaPlayer = MediaPlayer.create(this, notes[ii%4]); 
       m_mediaPlayer.start(); 
       try { 
        Thread.sleep(NOTE_DURATION); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
      } 
     } 
    } 

    private void end_music() { 
     if(initBkgdThread != null) { 
      initBkgdThread.interrupt(); 
      initBkgdThread = null; 
     } 
    } 

    boolean paused = false; 
    @Override 
    protected void onPause() { 
     paused = true; 
     super.onPause(); 
    } 
    @Override 
    protected void onResume() { 
     super.onResume(); 
     paused = false; 
    } 
} 

risposta

7

Si chiama interrupt() sul filo di gioco, ma è probabilmente in attesa nella sleep al momento. Questo catturerà il sonno per lanciare un InterruptedException. È necessario per la cattura di tale eccezione e uscire dal loop per fermare la riproduzione:

try { 
     Thread.sleep(NOTE_DURATION); 
    } catch (InterruptedException e) { 
     // XXX need to stop playing here, maybe return or break? 
     return; 
    } 

Poiché il interrupt() può anche venire in un momento diverso, è necessario verificare lo stato di interruzione e chiudere il ciclo:

if (!paused && !Thread.currentThread().isInterrupted()) { 
    ... 

Inoltre, tutte le variabili condivise tra due thread devono essere synchronized o contrassegnate con volatile. La bandiera paused dovrebbe probabilmente essere volatile qui:

volatile boolean paused = false 

Infine, per i posteri, quando si cattura InterruptedException, azzera lo stato di interruzione del filo. In genere è buona norma impostare immediatamente il flag di interrupt sul thread in modo che altri possano verificarlo:

try { 
     Thread.sleep(NOTE_DURATION); 
    } catch (InterruptedException e) { 
     // re-establish the interrupt condition 
     Thread.currentThread.interrupt(); 
     ... 
    } 
+0

Ha funzionato! Grazie per il vostro aiuto:] – Zero

+0

Non ho ottenuto l'ultimo punto, qual è la differenza tra l'esecuzione di 'return;' e il ripristino della condizione di interrupt. –

+1

Ogni volta che si cattura 'InterruptedException' lo stato dell'interrupt sul thread viene cancellato, quindi è necessario interrompere nuovamente il thread. Questo è uno schema importante in modo che se il codice si trova in una libreria, al chiamante verrà notificato che il thread è stato interrotto. È solo uno schema che menziono sempre @Muhammed Réfaat. – Gray

Problemi correlati