關於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 關鍵代碼
關鍵代碼