Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發 >> 關於android開發 >> 關於Activity銷毀,而繪制UI的子線程未銷毀出現的問題,activityui

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

編輯:關於android開發

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


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

一個例子:

我們都知道播放音頻要用到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 關鍵代碼 關鍵代碼

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved