关于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实例来实现. ...
随机推荐
- MongoDB 安装记录
之前使用一直没记录,防再次掉坑,记录下 echo 开始 D: cd D:\Program Files\MongoDB\Server\3.2\bin mongod --install --service ...
- Python - 获取帮助信息
1- Python Manuals 自带CHM格式的Python Manuals存放在\Python<x.x>\Doc\目录下.可以在IDLE界面下按F1键或点击help选项下Python ...
- AngularJS 五大特性,加快 Web 应用开发
AngularJS 是谷歌的一个 JavaScript 框架,旨在简化前端应用程序的开发.如果你在开发单页的应用程序,我敢肯定你已经听说过它.我是 AngularJS 的忠实粉丝,在这篇文章中我将概述 ...
- [Windows] 批处理文件系统服务控制
在cmd下可有两种方法打开,net和sc. net只能用于用于打开没有被禁用的服务. 启动: net start 服务名 停止: net stop 服务名 sc可打开被禁用的服务. sc config ...
- TCP/IP协议(一)
TCP/IP是Transmission Control Protocol/Internet Protocol的简写,中译名为传输控制协议/因特网互联协议,又名网络通讯协议,是Internet最基本的协 ...
- UPW学习资料整理 .NET C# 转
开发工具下载https://www.visualstudio.com/?Wt.mc_id=DX_MVP5000319 Windows 10 UWP开发视频1http://blogs.windows.c ...
- UWP开发入门(十五)——在FlipView中通过手势操作图片
本篇的最终目的,是模拟系统的照片APP可以左右滑动,缩放图片的操作.在实现的过程中,我们会逐步分析UWP编写UI的一些思路和技巧. 首先我们先实现一个横向的可以浏览图片的功能,也是大部分APP中的实现 ...
- IOS开发UI基础 UIDatePicker的属性
UIDatePicker • Locale设置DatePicker的地区,即设置DatePicker显示的语言.// 1.跟踪所有可用的地区,取出想要的地区 NSLog(@& ...
- IE11之F12 Developer Tools--概述篇
打开Developer Tools的方法: a. 点击F12 b. 在浏览器中选择Tools-->F12 Develooper Tools 打开后图示: 从上图我们可以看到,Developer ...
- .net开发微信公众平台
一.说明:公众平台信息接口为开发者提供了一种新的消息处理方式,只有申请成为开发者后,你才能使用公众平台的开发功能,在这里你需要填写一个URL和一个Token,这两项信息也需要你拥有自己的服务器(外网服 ...