关于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 关键代码
作者:听着music睡
出处:http://www.cnblogs.com/xqxacm/
Android交流群:38197636
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。