2012-03-20 39 views
6

Tôi đang tìm hiểu cách sử dụng các chuỗi trong Android và để làm điều đó, tôi đã tạo một ứng dụng nhỏ phát một chuỗi ghi chú. Ý tưởng là có một nút bắt đầu và nút kết thúc và (rõ ràng) nếu bạn nhấn nút bắt đầu, nó bắt đầu phát nhạc và nếu bạn nhấn nút kết thúc, nó sẽ dừng lại. Nút khởi động chỉ hoạt động tốt, nhưng vấn đề là nút kết thúc không hoạt động. Tôi đang gặp khó khăn trong việc tìm ra lý do tại sao, vì vậy có thể một số bạn có thể giúp tôi. Đây là mã:Chủ đề không làm gián đoạn

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; 
    } 
} 

Trả lời

7

Bạn đang kêu gọi interrupt() trên thread chơi nhưng nó có lẽ chờ đợi trong sleep vào thời điểm đó. Điều này sẽ bắt được giấc ngủ để ném một số InterruptedException. Bạn cần cập nhật thông rằng ngoại lệ thoát vòng lặp để dừng chơi:

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

Kể từ khi interrupt() cũng có thể đến vào một thời điểm khác nhau, bạn cần phải kiểm tra tình trạng gián đoạn và thoát vòng lặp của bạn:

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

Ngoài ra, tất cả các biến được chia sẻ giữa hai chuỗi cần phải là synchronized hoặc được đánh dấu volatile. Lá cờ paused có lẽ nên được volatile đây:

volatile boolean paused = false 

Cuối cùng, cho hậu thế, khi bạn bắt InterruptedException, nó xóa tình trạng ngắt của thread. Nó thường là thực hành tốt để ngay lập tức thiết lập cờ ngắt trên sợi để người khác có thể kiểm tra cho nó:

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

Nó hoạt động! Cảm ơn bạn đã giúp đỡ của bạn:] – Zero

+0

Tôi đã không nhận được điểm cuối cùng, sự khác biệt giữa thực hiện 'trở lại;' và tái thiết lập điều kiện gián đoạn là gì. –

+1

Bất cứ khi nào bạn nắm bắt 'InterruptedException', trạng thái ngắt trên luồng sẽ bị xóa, do đó bạn nên ngắt lại luồng. Đây là một mẫu quan trọng để nếu bạn viết mã trong thư viện, người gọi sẽ được thông báo rằng luồng đã bị gián đoạn. Nó chỉ là một mẫu mà tôi luôn đề cập đến @MuhammedRefaat. – Gray

Các vấn đề liên quan