關於Activity銷毀,而繪制UI的子線程未銷毀出現的問題


項目總結

---------------------------------------------------------------------------------------------------------

有一個功能模塊,需要播放音頻,畫一個簡單的界面

一個例子:

我們都知道播放音頻要用到MediaPlayer類,我這里,不需要開啟Service,就在本Activity播放音頻,當Activity銷毀的時候,音頻便結束

但是有一個重點,需要即時的變化當前播放的時間

我的思路是,開啟一個線程,計算當前音頻的剩余播放時間,如果>0 則用Handler循環發送一個消息來更改時間UI

Thread tPlay ;
tPlay = new Thread(new Runnable() {
            @Override
            public void run() {
                int time = (mPlay.getDuration()-mPlay.getCurrentPosition())/1000;  // 獲得當前的音頻的剩余時間,總時長-當前播放時長
                while(time>0&&mPlay!=null) {                                       // 如果剩余時間>0 並且MediaPlayer對象存在,就需要沒0.2秒更新一下時間UI
                    try {
                        Thread.sleep(200);
                        time = (mPlay.getDuration()-mPlay.getCurrentPosition())/1000; //獲得當前時間
                        final int finalTime = time;
                        handler.post(new Runnable() {
                            @Override
                            public void run() {
                                topic_play_time.setText(finalTime /60+"'"+ finalTime %60); //更改UI } });
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });

 

然后有線程對象了,什么時候start呢,必然是在第一次播放音頻的時候,而且只能start一次。

 

那么問題來了。當我播放音頻的時候,或者暫停已經播放一段的音頻的時候,用戶可能會退出Activity ,

而Activity銷毀了,但是這個Activity開啟的計算時間更改UI的子線程還存在,它還需要循環計算剩余時間,但是MediaPlayer對象沒了,就報錯了。

 

所以,解決方法只能是銷毀Activity之前結束這個Activity開啟的子線程。

試過幾種方法,最后選定了一個最簡單,最易理解的方法:

1、設置一個全局標記變量boolean flag = true;

2、線程中while 循環判斷 flag 是否為true,是則執行內部代碼,否則不執行,結束循環了,即線程也隨之結束了

tPlay = new Thread(new Runnable() {
            @Override
            public void run() {
                int time = (mPlay.getDuration()-mPlay.getCurrentPosition())/1000;
                while(time>0&&mPlay!=null&&flag) {
                }
            }
        });

 

3、在Activity銷毀的

@Override
protected void onDestroy() {
    super.onDestroy();
    isflag=false;
}

 

方法中更改flag,那么線程中while條件則不成立,線程就結束了,也不會再報錯了。

 

貼一下關鍵代碼:

  1 public class TopicDetailActivity extends Activity implements View.OnClickListener {
  2 
  3     private ImageButton topic_play_music;
  4 
  5     private Attention entity;
  6 
  7     private boolean isflag= true;
  8     private MediaPlayer mPlay;
  9     private Thread tPlay;
 10     private Handler handler = new Handler(){
 11         @Override
 12         public void handleMessage(Message msg) {
 13             super.handleMessage(msg);
 14 
 15         }
 16     };
 17     @Override
 18     protected void onCreate(Bundle savedInstanceState) {
 19         super.onCreate(savedInstanceState);
 20         setContentView(R.layout.activity_topic_detail);
 21 
 22         Intent intent = getIntent();
 23         Serializable attention = intent.getSerializableExtra("attention");
 24         tPlay = new Thread(new Runnable() {
 25             @Override
 26             public void run() {
 27                 int time = (mPlay.getDuration()-mPlay.getCurrentPosition())/1000;
 28                 while(time>0&&mPlay!=null&&isflag) {
 29                     try {
 30                         Thread.sleep(200);
 31                         time = (mPlay.getDuration()-mPlay.getCurrentPosition())/1000;
 32                         final int finalTime = time;
 33                         handler.post(new Runnable() {
 34                             @Override
 35                             public void run() {
 36                                 topic_play_time.setText(finalTime /60+"'"+ finalTime %60);
 37                             }
 38                         });
 39                     } catch (InterruptedException e) {
 40                         e.printStackTrace();
 41                     }
 42                 }
 43             }
 44         });
 45         initView();
 46         initData(attention);
 47     }
 48 
 49     /**
 50      * 數據展示
 51      * @param attention
 52      */
 53     private void initData(Serializable attention) {
 54         entity = (Attention) attention;
 55        
 56         int nowTime = Integer.parseInt(entity.getAudiolength());
 57         topic_play_time.setText(nowTime/60 + "'" + nowTime%60);
 58         
 59 
 60 
 61 
 62     }
 63 
 64 
 65     /**
 66      * 初始化控件
 67      */
 68     private void initView() {
 69         topic_play_music = (ImageButton) findViewById(R.id.topic_play_music);
 70 
 71         topic_play_music.setOnClickListener(this);
 72     }
 73 
 74     @Override
 75     public void onClick(View v) {
 76         switch (v.getId()){
 77             
 78             case R.id.topic_play_music:
 79                 if(mPlay==null){
 80                     mPlay = new MediaPlayer();
 81                     mPlay.reset();
 82                     try {
 83                         mPlay.setDataSource("http://imagecdn.xunjimap.com/image/" + entity.getAudiourl());
 84                         mPlay.prepare();
 85                         topic_play_music.setImageResource(R.mipmap.ui_detail_pause);
 86                         mPlay.start();
 87                         tPlay.start();
 88                     } catch (IOException e) {
 89                         e.printStackTrace();
 90                     }
 91                 }else{
 92                     if (mPlay.isPlaying()){
 93                         mPlay.pause();
 94                         topic_play_music.setImageResource(R.mipmap.ui_detail_play);
 95                     }else{
 96                         mPlay.start();
 97                         topic_play_music.setImageResource(R.mipmap.ui_detail_pause);
 98                     }
 99                 }
100                 break;
101         }
102     }
103 
104     @Override
105     protected void onDestroy() {
106         super.onDestroy();
107         isflag=false;
108         try {
109             tPlay.sleep(500);
110         } catch (InterruptedException e) {
111             e.printStackTrace();
112         }
113         if (mPlay!=null){
114             mPlay.stop();
115 
116             mPlay.release();
117         }
118     }
119 
120 
121 }
122 
123 關鍵代碼
關鍵代碼

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM