你的位置:首页 > 操作系统

[操作系统]关于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 关键代码

关键代码