当前位置: 代码迷 >> Android >> 关于Activity销毁,而绘制UI的子线程未销毁出现的有关问题
  详细解决方案

关于Activity销毁,而绘制UI的子线程未销毁出现的有关问题

热度:72   发布时间:2016-04-27 22:12:44.0
关于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销毁的

@Overrideprotected 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     @Override105     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 关键代码
关键代码

 

2楼KillU
为什么进程都推出了 线成还在?
Re: 听着music睡
@KillU,实际上线程还是存在的,可以做个测试,开启一个子线程 while 死循环 来设置一个TextView 文本信息,看看退出进程后,是不是会报错
1楼奔跑的蜗牛丶
播放视屏之前 VideoView是不是黑的?楼主有碰到这种情况吗?
Re: 听着music睡
@奔跑的蜗牛丶,是播放界面出来之前黑的闪一下,还是黑到播放界面出来,还是你视频播放自动到转横屏并闪黑一下
  相关解决方案