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

时间:2022-11-02 18:42:39

项目总结

---------------------------------------------------------------------------------------------------------

有一个功能模块,需要播放音频,画一个简单的界面

一个例子:

关于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())/; // 获得当前的音频的剩余时间,总时长-当前播放时长
while(time>&&mPlay!=null) { // 如果剩余时间>0 并且MediaPlayer对象存在,就需要没0.2秒更新一下时间UI
try {
Thread.sleep();
time = (mPlay.getDuration()-mPlay.getCurrentPosition())/; //获得当前时间
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())/;
while(time>&&mPlay!=null&&flag) {
}
}
});

3、在Activity销毁的

@Override
protected void onDestroy() {
super.onDestroy();
isflag=false;
}

方法中更改flag,那么线程中while条件则不成立,线程就结束了,也不会再报错了。

贴一下关键代码:

 public class TopicDetailActivity extends Activity implements View.OnClickListener {

     private ImageButton topic_play_music;

     private Attention entity;

     private boolean isflag= true;
private MediaPlayer mPlay;
private Thread tPlay;
private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg); }
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_topic_detail); Intent intent = getIntent();
Serializable attention = intent.getSerializableExtra("attention");
tPlay = new Thread(new Runnable() {
@Override
public void run() {
int time = (mPlay.getDuration()-mPlay.getCurrentPosition())/;
while(time>&&mPlay!=null&&isflag) {
try {
Thread.sleep();
time = (mPlay.getDuration()-mPlay.getCurrentPosition())/;
final int finalTime = time;
handler.post(new Runnable() {
@Override
public void run() {
topic_play_time.setText(finalTime /+"'"+ finalTime %);
}
});
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
initView();
initData(attention);
} /**
* 数据展示
* @param attention
*/
private void initData(Serializable attention) {
entity = (Attention) attention; int nowTime = Integer.parseInt(entity.getAudiolength());
topic_play_time.setText(nowTime/ + "'" + nowTime%); } /**
* 初始化控件
*/
private void initView() {
topic_play_music = (ImageButton) findViewById(R.id.topic_play_music); topic_play_music.setOnClickListener(this);
} @Override
public void onClick(View v) {
switch (v.getId()){ case R.id.topic_play_music:
if(mPlay==null){
mPlay = new MediaPlayer();
mPlay.reset();
try {
mPlay.setDataSource("http://imagecdn.xunjimap.com/image/" + entity.getAudiourl());
mPlay.prepare();
topic_play_music.setImageResource(R.mipmap.ui_detail_pause);
mPlay.start();
tPlay.start();
} catch (IOException e) {
e.printStackTrace();
}
}else{
if (mPlay.isPlaying()){
mPlay.pause();
topic_play_music.setImageResource(R.mipmap.ui_detail_play);
}else{
mPlay.start();
topic_play_music.setImageResource(R.mipmap.ui_detail_pause);
}
}
break;
}
} @Override
protected void onDestroy() {
super.onDestroy();
isflag=false;
try {
tPlay.sleep();
} catch (InterruptedException e) {
e.printStackTrace();
}
if (mPlay!=null){
mPlay.stop(); mPlay.release();
}
} } 关键代码

关键代码

关于Activity销毁,而绘制UI的子线程未销毁出现的问题的更多相关文章

  1. android 不能在子线程中更新ui的讨论和分析

    问题描写叙述 做过android开发基本都遇见过 ViewRootImpl$CalledFromWrongThreadException,上网一查,得到结果基本都是仅仅能在主线程中更改 ui.子线程要 ...

  2. Android 子线程无法刷新UI界面

    问题:在Android开发中,子线程无法直接更改UI界面视图的刷新 这个时候 Handler 起到了至关重要的作用. 简单来说 , Handler就是用来传递消息的. Handler可以当成子线程与主 ...

  3. Python_线程、线程效率测试、数据隔离测试、主线程和子线程

    0.进程中的概念 三状态:就绪.运行.阻塞 就绪(Ready):当进程已分配到除CPU以外的所有必要资源,只要获得处理机便可立即执行,这时的进程状态成为就绪状态. 执行/运行(Running)状态:当 ...

  4. Java并发编程原理与实战六:主线程等待子线程解决方案

    本文将研究的是主线程等待所有子线程执行完成之后再继续往下执行的解决方案 public class TestThread extends Thread { public void run() { Sys ...

  5. C#定时检測子线程是否已经完毕

    C#定时检測子线程是否已经完毕 class Program { static void Main(string[] args) { //主线程中启动一个支线程,运行doSomething这种一个方法. ...

  6. python3 结束子线程

    最近公司内部网络经常出问题,奇慢无比,导致人脸检测程序在下载图片时经常卡住,为了不影响数据的核对, 决定在网络不佳图片下载超时后放弃下载,继续执行后续程序. 于是整理出解决思路如下: 1.在线程中完成 ...

  7. (转)Android在子线程中更新Activity中UI的方法

    转:http://blog.sina.com.cn/s/blog_3fe961ae0100mvc5.html 在Android平台下,进行多线程编程时,经常需要在主线程之外的一个单独的线程中进行某些处 ...

  8. Android 子线程更新UI 异常

    众所周知,Android是不可以在子线程中直接更新UI的,需要借助Handler或者View.post(Runnable runnable)或者runOnUIThread(Runnable runna ...

  9. Android多线程之(一)View.post()源码分析——在子线程中更新UI

    提起View.post(),相信不少童鞋一点都不陌生,它用得最多的有两个功能,使用简便而且实用: 1)在子线程中更新UI.从子线程中切换到主线程更新UI,不需要额外new一个Handler实例来实现. ...

随机推荐

  1. 移动端-js触摸事件

    开发者工具 在移动开发中,一种较为容易的做法是,先在桌面上开始原型设计,然后再在打算要支持的设备上处理移动特有的部分.多点触摸正是难以在PC上进行测试的那些功能之一,因为大部分的PC都没有触摸输入. ...

  2. [SQL] SQL SERVER基础语法

    Struct Query Language 1.3NF a.原子性 b.不能数据冗余 c.引用其他表的主键 2.约束 a.非空约束 b.主键约束 c.唯一约束 d.默认约束 e.检查约束 f.外键约束 ...

  3. [转]说说C语言运算符的“优先级”与“结合性”

    补充自己的一点理解: 1.关于++i 与 i++的区别. ++i 和 i++如果是单独使用的语句,即二者后面均加上分号,或者其他单独使用的语句,没有任何区别.例如: for(i=0;i<100; ...

  4. Linux安装配置JDK

    如果想看Windows下的安装,请访问此链接: http://www.cnblogs.com/yoyotl/p/5101321.html 1. 去官网下载Linux版本的jdk安装包,(我下载的是ta ...

  5. Jsensation &vert; 氪加

    Jsensation | 氪加 www.jsensation.com

  6. Building roads

    Building roads Time Limit: 10000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Tot ...

  7. 在Windows上安装Git

    实话实说,Windows是最烂的开发平台,如果不是开发Windows游戏或者在IE里调试页面,一般不推荐用Windows.不过,既然已经上了微软的贼船,也是有办法安装Git的. Windows下要使用 ...

  8. xml 转换成对象&lpar;采用反射机制对对对象属性赋值&rpar;

    /// <summary> /// 采用反射机制对对对象属性赋值 /// </summary> /// <param name="node">& ...

  9. 关于枚举,enum、Enum、EnumSet、RegularEnumSet、JumboEnumSet

    Apache Commons Lang. 在版本3中,enum相关的工具就留下EnumUtils. 首先, 所有enum,都默认实现了抽象类 java.lang.Enum .所以,所有enum都具备E ...

  10. centos 7 安装jdk1&period;8

    首先下载jdk1.8  去官网下载jdk:http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151. ...