【转】Android 定时器实现的几种方式和removeCallbacks失效问题详解--不错
原文网址:http://blog.csdn.net/xiaanming/article/details/9011193
实现定时器有很多种方式,在这里我简单的介绍几种方式
(1)使用Handler + Runnable的方式
- Handler handler = new Handler();
- Runnable runnable = new Runnable() {
- @Override
- public void run() {
- //你要做的事
- //......
- System.out.println(Thread.currentThread().getName());
- handler.postDelayed(runnable, 1000);
- }
- };
然后调用handler.post(runnable);就能启动定时器,这里是每隔1s打印线程名字,从打印中我们可以知道,他并没有另开线程,而是运行在UI线程当中,当你要取消定时器的时候,只需要调用handler.removeCallbacks(runnable)就可以了。
上面中有一个问题,有时候你会发现removeCallbacks有时候会失效,不能从消息队列中移除,看下面的demo
图:两个按钮,一个将Runnable加到消息队列中,一个将Runnable从消息队列中移除。该Runnable每1秒钟打印一次日志。
- <span style="font-family:Courier New;">package com.example.demoactivity;
- import android.app.Activity;
- import android.os.Bundle;
- import android.os.Handler;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.widget.Button;
- public class TimerActivity extends Activity{
- Handler handler = new Handler();
- Runnable runnable = new Runnable() {
- @Override
- public void run() {
- System.out.println("update...");
- handler.postDelayed(runnable, 1000);
- }
- };
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.timer);
- Button mButtonStart = (Button) findViewById(R.id.button1);
- Button mButtonStop = (Button) findViewById(R.id.button2);
- mButtonStart.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- handler.post(runnable);
- }
- });
- mButtonStop.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- handler.removeCallbacks(runnable);
- }
- });
- }
- }</span><span style="font-family: Georgia, 'Times new roman', Times, san-serif;">
- </span>
结果:
(1)start –> 输出 –> stop–> 停止输出
(2)start –> 输出 –> Background –> Front –> stop->继续输出
当Activity进入后台运行后再转入前台运行,removeCallbacks无法将updateThread从message queue中移除。
这是为什么呢?
在Activity由前台转后台过程中,线程是一直在运行的,但是当Activity转入前台时会重新定义Runnable runnable;也就是说此时从message queue移除的runnable与原先加入message queue中的runnable并非是同一个对象。如果把runnable定义为静态的则removeCallbacks不会失效,对于静态变量在内存中只有一个拷贝(节省内存),JVM只为静态分配一次内存,在加载类的过程中完成静态变量的内存分配,我们做如下修改就能解决上面的这个问题
“在Activity由前台转后台过程中,线程是一直在运行的,但是当Activity转入前台时会重新定义Runnable runnable”应该不会重新定义Runnable runnable。
- static Handler handler = new Handler();
- static Runnable runnable = new Runnable() {
- @Override
- public void run() {
- System.out.println("update...");
- handler.postDelayed(runnable, 1000);
- }
- };
(2)使用Timer的方式
- Timer timer = new Timer();
- timer.schedule(new TimerTask() {
- @Override
- public void run() {
- System.out.println("update....");
- }
- }, 0, 1000);
上面的每一秒打印语句,run方法是运行在子线程,不能直接在里面更新UI操作,这里需要注意下,取消的话调用timer.cancel()就能移除任务了
(3)采用Handle与线程的sleep(long )方法
1.定义一个Handler类,用于处理接受到的Message
- Handler handler = new Handler() {
- public void handleMessage(Message msg) {
- super.handleMessage(msg);
- System.out.println("update...");
- }
- }
2.新建一个实现Runnable接口的线程类,用一个boolean 来控制线程开始和结束 boolean isLive = true如下:
- public class MyThread implements Runnable {
- @Override
- public void run() {
- while (isLive) {
- try {
- Thread.sleep(1000);// 线程暂停1秒,单位毫秒
- Message message = new Message();
- message.what = 1;
- handler.sendMessage(message);// 发送消息
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- }
3.在需要启动线程的地方加入下面语句
- new Thread(new MyThread()).start();
4.取消的话将isLive设置为false就行了
今天主要介绍这三种方法,写的不好的地方希望大家指出,谢谢!
【转】Android 定时器实现的几种方式和removeCallbacks失效问题详解--不错的更多相关文章
- Android 定时器实现的几种方式和removeCallbacks失效问题详解
实现定时器有很多种方式,在这里我简单的介绍几种方式 (1)使用Handler + Runnable的方式 Handler handler = new Handler(); Runnable runna ...
- Form_Form页面跳转的四种方式(open_form, call_form, new_form, fnd_function)详解(汇总)
2014-06-29 Created By BaoXinjian
- uni-app&H5&Android混合开发三 || uni-app调用Android原生方法的三种方式
前言: 关于H5的调用Android原生方法的方式有很多,在该片文章中我主要简单介绍三种与Android原生方法交互的方式. 一.H5+方法调用android原生方法 H5+ Android开发规范官 ...
- JAVA高级架构师基础功:Spring中AOP的两种代理方式:动态代理和CGLIB详解
在spring框架中使用了两种代理方式: 1.JDK自带的动态代理. 2.Spring框架自己提供的CGLIB的方式. 这两种也是Spring框架核心AOP的基础. 在详细讲解上述提到的动态代理和CG ...
- Android开发之手势滑动(滑动手势监听)详解
Android开发之手势滑动(滑动手势监听)详解 在Android应用中,经常需要手势滑动操作,比如上下滑动,或左右方向滑动,处理手势滑动通常有两种方法:一种是单独实现setOnTouchListen ...
- jQuery插件开发的两种方法及$.fn.extend的详解(转)
jQuery插件开发的两种方法及$.fn.extend的详解 jQuery插件开发分为两种:1 类级别.2 对象级别,下面为大家详细介绍下 jQuery插件开发分为两种: 1 类级别 类级别你可以 ...
- Android Studio一直显示Building“project name”Gradle project info问题详解
关注我,每天都有优质技术文章推送,工作,学习累了的时候放松一下自己. 本篇文章同步微信公众号 欢迎大家关注我的微信公众号:「醉翁猫咪」 Android Studio一直显示 Building&quo ...
- Android 更新UI的几种方式
1.Activity的 runOnUiThread textView = (TextView) findViewById( R.id.tv ); new Thread(new Runnable() { ...
- Android请求服务器的两种方式--post, get的区别
android中用get和post方式向服务器提交请求_疯狂之桥_新浪博客http://blog.sina.com.cn/s/blog_a46817ff01017yxt.html Android提交数 ...
随机推荐
- 关于XMLEncoder和XMLDecoder
我们用XMLEncoder和XMLDecoder来序列化和反序列化一个类. 我觉得需要注意的是,我们在new一个对象的时候,XMLEncoder本身默认的是类中无参的构造函数,我今儿在实现的时候,老是 ...
- sqlserver2012关于allwayson和复制结合起来的做法以及需要注意的问题
allwayson的自动故障转移需要它对应的windows故障转移群集有仲裁设置,这样相当于三台以上的服务器做allwayson才比较合适 1.首先安装sqlserver的时候需要勾选上“复制” ...
- Python学习日志(六)
字符串的方法及注释 字符串转义字符含义 字符串格式化符号含义 eg:'a'的ASCii码是97 格式化操作符辅助指令 format()字符串格式化方法 字符串的格式化是指统一字符串格式 format( ...
- [小知识] 获取浏览器UA标识
这个随笔纯粹是小知识的积累,以后都会打上小知识的标签. 经常见的,下载移动app时,只有一个二维码,但扫码后,会根据手机是iphone还是android下载不同app,下面就是这个操作的代码: < ...
- 魅蓝Note有几种颜色 魅蓝Note哪个颜色好看
http://www.pc841.com/shoujizhishi/39882.html http://news.mydrivers.com/1/359/359443.htm 魅族发布首款千元高性价比 ...
- Swift学习笔记十六:协议
Protocol(协议)用于统一方法和属性的名称,而不实现不论什么功能. 协议可以被类.枚举.结构体实现.满足协议要求的类,枚举,结构体被称为协议的遵循者. 遵循者须要提供协议指定的成员,如属性,方法 ...
- android应用中设置自动大写
给要添加view里面添加android:capitalize="sentences"属性
- CentOS6.x升级MySQL版本号5.1到5.6
有一些虚拟机.云主机提供商仍然使用的是老版本号的安装套件. 预装的应用软件版本号非常低. 比方 techbrood.com 使用的云server,当中MySQL预装版本号为老版本号5.1.x. 而最新 ...
- js验证表单并提交
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- mybatis 与 反射
Mybatis是个优秀的ORM框架,所以它的反射层一定不会让我们失望 图比较大,可以开新页面查看 可以看到,Mybatis对这一块抽象的比较复杂,我们可以看到有几个比较主要的部分:Reflector. ...