关于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的子线程未销毁出现的问题的更多相关文章
- android 不能在子线程中更新ui的讨论和分析
问题描写叙述 做过android开发基本都遇见过 ViewRootImpl$CalledFromWrongThreadException,上网一查,得到结果基本都是仅仅能在主线程中更改 ui.子线程要 ...
- Android 子线程无法刷新UI界面
问题:在Android开发中,子线程无法直接更改UI界面视图的刷新 这个时候 Handler 起到了至关重要的作用. 简单来说 , Handler就是用来传递消息的. Handler可以当成子线程与主 ...
- Python_线程、线程效率测试、数据隔离测试、主线程和子线程
0.进程中的概念 三状态:就绪.运行.阻塞 就绪(Ready):当进程已分配到除CPU以外的所有必要资源,只要获得处理机便可立即执行,这时的进程状态成为就绪状态. 执行/运行(Running)状态:当 ...
- Java并发编程原理与实战六:主线程等待子线程解决方案
本文将研究的是主线程等待所有子线程执行完成之后再继续往下执行的解决方案 public class TestThread extends Thread { public void run() { Sys ...
- C#定时检測子线程是否已经完毕
C#定时检測子线程是否已经完毕 class Program { static void Main(string[] args) { //主线程中启动一个支线程,运行doSomething这种一个方法. ...
- python3 结束子线程
最近公司内部网络经常出问题,奇慢无比,导致人脸检测程序在下载图片时经常卡住,为了不影响数据的核对, 决定在网络不佳图片下载超时后放弃下载,继续执行后续程序. 于是整理出解决思路如下: 1.在线程中完成 ...
- (转)Android在子线程中更新Activity中UI的方法
转:http://blog.sina.com.cn/s/blog_3fe961ae0100mvc5.html 在Android平台下,进行多线程编程时,经常需要在主线程之外的一个单独的线程中进行某些处 ...
- Android 子线程更新UI 异常
众所周知,Android是不可以在子线程中直接更新UI的,需要借助Handler或者View.post(Runnable runnable)或者runOnUIThread(Runnable runna ...
- Android多线程之(一)View.post()源码分析——在子线程中更新UI
提起View.post(),相信不少童鞋一点都不陌生,它用得最多的有两个功能,使用简便而且实用: 1)在子线程中更新UI.从子线程中切换到主线程更新UI,不需要额外new一个Handler实例来实现. ...
随机推荐
- [LeetCode] Pow(x, n) 二分搜索
Implement pow(x, n). Hide Tags Math Binary Search 题目很简单的. class Solution { public: double pow( ...
- HTML5大数据可视化效果(二)可交互地铁线路图
前言 最近特别忙,承蒙大伙关照,3D机房的项目一个接着一个,领了一帮小弟,搞搞传帮带,乌飞兔走,转眼已经菊黄蟹肥……有个小弟很不错,勤奋好学,很快就把API都摸透了,自己折腾着做了个HTML5的魔都的 ...
- iOS app开发资料整理
Objective C快速入门: http://blog.csdn.net/totogo2010/article/details/7632384 http://www.cocoachina.com/i ...
- 受限玻尔兹曼机(RBM)学习笔记(八)RBM 的评估
去年 6 月份写的博文<Yusuke Sugomori 的 C 语言 Deep Learning 程序解读>是囫囵吞枣地读完一个关于 DBN 算法的开源代码后的笔记,当时对其中涉及的算 ...
- Tools - RSS
RSS RSS是在线共享和阅读内容的一种方式,能够简洁高效地获取订阅内容的更新. 全称Really Simple Syndication (真正简易联合),也叫聚合内容. 有选择地浏览感兴趣的以及与工 ...
- C#语法糖之Cookies操作类 asp.net
用法: //声名一个数据集合 var listString = new List<string>() { "a", "b", "c&quo ...
- 微软IIS对http keep-alive的“霸道”处理
大家都知道在IIS中有个HTTP keep-alive设置,见下图: 很多人可能和我们一样,以为这样设置后,IIS会就在发送响应内容时加上这个http header——Connection: keep ...
- 另一个 OleDbParameterCollection 中已包含 OleDbParameter 错误分析及解决办法
程序非常简单,就是从一个表中取出一个符合要求的数据,如果取到,就把该数据对应的计数加1.也就是执行不同的两个SQL语句操作同一个表,并且这两个SQL的参数是一样的.在一个函数里完成这个调用.执行第二个 ...
- CentOS6.5菜鸟之旅:安装Realtek无线网卡驱动
一.前言 CentOS6.5不像CentOS7和Unbuntu那样自动安装好了无线网卡驱动,因此需要我们折腾一下. 二.安装前的准备工作 [a] 检查无线网卡驱动的安装情况(通过查看网络接口的安装 ...
- Flex 布局相关用法
前言: 布局的传统解决方案,基于盒状模型,依赖 display属性 + position属性 + float属性.它对于那些特殊布局非常不方便,比如,垂直居中 就不容易实现. 2009年,W3C提出了 ...