Android中定时器Timer和TimerTask的启动,停止,暂停,继续等操作实例

下面是一个在Android中使用定时器Timer和TimerTask的启动,停止,暂停,继续等操作的demo。

需要注意的问题主要有两点:

1、Timer和TimerTask在调用cancel()取消后不能再执行 schedule语句,否则提示出错,提示如下:

D/AndroidRuntime( 6672): Shutting down VM
W/dalvikvm( 6672): threadid=1: thread exiting with uncaught exception (group=0x40018560)
E/AndroidRuntime( 6672): FATAL EXCEPTION: main
E/AndroidRuntime( 6672): java.lang.IllegalStateException: Timer was canceled
E/AndroidRuntime( 6672): 	at java.util.Timer.scheduleImpl(Timer.java:563)
E/AndroidRuntime( 6672): 	at java.util.Timer.schedule(Timer.java:483)
E/AndroidRuntime( 6672): 	at com.snowdream.timerdemo.TimerDemoActivity$2.onClick(TimerDemoActivity.java:73)
E/AndroidRuntime( 6672): 	at android.view.View.performClick(View.java:2501)
E/AndroidRuntime( 6672): 	at android.view.View$PerformClick.run(View.java:9107)
E/AndroidRuntime( 6672): 	at android.os.Handler.handleCallback(Handler.java:587)
E/AndroidRuntime( 6672): 	at android.os.Handler.dispatchMessage(Handler.java:92)
E/AndroidRuntime( 6672): 	at android.os.Looper.loop(Looper.java:130)
E/AndroidRuntime( 6672): 	at android.app.ActivityThread.main(ActivityThread.java:3835)
E/AndroidRuntime( 6672): 	at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime( 6672): 	at java.lang.reflect.Method.invoke(Method.java:507)
E/AndroidRuntime( 6672): 	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:841)
E/AndroidRuntime( 6672): 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:599)
E/AndroidRuntime( 6672): 	at dalvik.system.NativeStart.main(Native Method)
W/ActivityManager(  154):   Force finishing activity com.snowdream.timerdemo/.TimerDemoActivity
W/ActivityManager(  154): Activity pause timeout for HistoryRecord{40550560 com.snowdream.timerdemo/.TimerDemoActivity}
W/ActivityManager(  154): Activity destroy timeout for HistoryRecord{40550560 com.snowdream.timerdemo/.TimerDemoActivity}
D/dalvikvm(  800): GC_EXPLICIT freed 13K, 58% free 3127K/7431K, external 0K/0K, paused 70ms
D/dalvikvm(  562): GC_EXPLICIT freed 59K, 51% free 2935K/5959K, external 245K/512K, paused 84ms
I/ActivityManager(  154): Start proc com.android.email for service com.android.email/.service.MailService: pid=6691 uid=10019 gids={3003, 1015}

2、只能在UI主线程中更新控件/组件。在其他线程中,更新控件/组件,会提示出错,提示如下:

(注:这种情况下,可以通过Hander发送消息的方式来更新控件/组件,详情参考例子。)

E/AndroidRuntime( 6309): android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
E/AndroidRuntime( 6309): 	at android.view.ViewRoot.checkThread(ViewRoot.java:2941)
E/AndroidRuntime( 6309): 	at android.view.ViewRoot.invalidateChild(ViewRoot.java:643)
E/AndroidRuntime( 6309): 	at android.view.ViewRoot.invalidateChildInParent(ViewRoot.java:669)
E/AndroidRuntime( 6309): 	at android.view.ViewGroup.invalidateChild(ViewGroup.java:2511)
E/AndroidRuntime( 6309): 	at android.view.View.invalidate(View.java:5296)
E/AndroidRuntime( 6309): 	at android.widget.TextView.checkForRelayout(TextView.java:5533)
E/AndroidRuntime( 6309): 	at android.widget.TextView.setText(TextView.java:2730)
E/AndroidRuntime( 6309): 	at android.widget.TextView.setText(TextView.java:2598)
E/AndroidRuntime( 6309): 	at android.widget.TextView.setText(TextView.java:2573)
E/AndroidRuntime( 6309): 	at com.snowdream.timerdemo.TimerDemoActivity$1.run(TimerDemoActivity.java:48)
E/AndroidRuntime( 6309): 	at java.util.Timer$TimerImpl.run(Timer.java:284)

Demo源码如下:

TimerDemoActivity.java

package com.snowdream.timerdemo;

import java.util.Timer;
import java.util.TimerTask;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class TimerDemoActivity extends Activity {

	private static String  TAG = "TimerDemo";

	private TextView mTextView = null;
	private Button mButton_start = null;
	private Button mButton_pause = null;

	private Timer mTimer = null;
	private TimerTask mTimerTask = null;

	private Handler mHandler = null;

	private static int count = 0;
	private boolean isPause = false;
	private boolean isStop = true;

	private static int delay = 1000;  //1s
	private static int period = 1000;  //1s

	private static final int UPDATE_TEXTVIEW = 0;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		mTextView = (TextView)findViewById(R.id.mytextview);
		mButton_start = (Button)findViewById(R.id.mybutton_start);
		mButton_pause = (Button)findViewById(R.id.mybutton_pause);

		mButton_start.setOnClickListener(new Button.OnClickListener() {
			public void onClick(View v) {
				if (isStop) {
					Log.i(TAG, "Start");
				} else {
					Log.i(TAG, "Stop");
				}

				isStop = !isStop;

				if (!isStop) {
					startTimer();
				}else {
					stopTimer();
				}

				if (isStop) {
					mButton_start.setText(R.string.start);
				} else {
					mButton_start.setText(R.string.stop);
				}
			}
		});

		mButton_pause.setOnClickListener(new Button.OnClickListener() {
			public void onClick(View v) {
				if (isPause) {
					Log.i(TAG, "Resume");
				} else {
					Log.i(TAG, "Pause");
				}

				isPause = !isPause;

				if (isPause) {
					mButton_pause.setText(R.string.resume);
				} else {
					mButton_pause.setText(R.string.pause);
				}
			}
		});

		mHandler = new Handler(){

			@Override
			public void handleMessage(Message msg) {
				switch (msg.what) {
				case UPDATE_TEXTVIEW:
					updateTextView();
					break;
				default:
					break;
				}
			}
		};
	}

	private void updateTextView(){
		mTextView.setText(String.valueOf(count));
	}

	private void startTimer(){
		if (mTimer == null) {
			mTimer = new Timer();
		}

		if (mTimerTask == null) {
			mTimerTask = new TimerTask() {
				@Override
				public void run() {
					Log.i(TAG, "count: "+String.valueOf(count));
					sendMessage(UPDATE_TEXTVIEW);

					do {
						try {
							Log.i(TAG, "sleep(1000)...");
							Thread.sleep(1000);
						} catch (InterruptedException e) {
						}
					} while (isPause);

					count ++;
				}
			};
		}

		if(mTimer != null && mTimerTask != null )
			mTimer.schedule(mTimerTask, delay, period);

	}

	private void stopTimer(){

		if (mTimer != null) {
			mTimer.cancel();
			mTimer = null;
		}

		if (mTimerTask != null) {
			mTimerTask.cancel();
			mTimerTask = null;
		}	

		count = 0;

	}

	public void sendMessage(int id){
		if (mHandler != null) {
			Message message = Message.obtain(mHandler, id);
			mHandler.sendMessage(message);
		}
	}
}

layout-main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/mytextview"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="@string/number" />

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:orientation="horizontal" >

        <Button
            android:id="@+id/mybutton_start"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/start" />

        <Button
            android:id="@+id/mybutton_pause"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/pause" />
    </LinearLayout>

</LinearLayout>

strings.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="app_name">TimerDemo</string>
    <string name="number">0</string>
    <string name="start">start</string>
    <string name="stop">stop</string>
    <string name="pause">pause</string>
    <string name="resume">resume</string>

</resources>

源码下载:

http://download.csdn.net/detail/yang_hui1986527/3922447

时间: 2024-11-01 14:38:26

Android中定时器Timer和TimerTask的启动,停止,暂停,继续等操作实例的相关文章

Java中的Timer和TimerTask在Android中的用法

在开发中我们有时会有这样的需求,即在固定的每隔一段时间执行某一个任务.比如UI上的控件需要随着时间改变,我们可以使用Java为我们提供的计时器的工具类,即Timer和TimerTask. Timer是一个普通的类,其中有几个重要的方法:而TimerTask则是一个抽象类,其中有一个抽象方法run(),类似线程中的run()方法,我们使用Timer创建一个他的对象,然后使用这对象的schedule方法来完成这种间隔的操作. schedule方法有三个参数 第一个参数就是TimerTask类型的对象

解析Java中的Timer和TimerTask在Android中的用法和实例_java

在开发中我们有时会有这样的需求,即在固定的每隔一段时间执行某一个任务.比如UI上的控件需要随着时间改变,我们可以使用Java为我们提供的计时器的工具类,即Timer和TimerTask. Timer是一个普通的类,其中有几个重要的方法:而TimerTask则是一个抽象类,其中有一个抽象方法run(),类似线程中的run()方法,我们使用Timer创建一个他的对象,然后使用这对象的schedule方法来完成这种间隔的操作. schedule方法有三个参数 第一个参数就是TimerTask类型的对象

Android中定时器的3种实现方法

在Android开发中,定时器一般有以下3种实现方法: 一.采用Handler与线程的sleep(long)方法 二.采用Handler的postDelayed(Runnable, long)方法 三.采用Handler与timer及TimerTask结合的方法 下面逐一介绍: 一.采用Handle与线程的sleep(long)方法 Handler主要用来处理接受到的消息.这只是最主要的方法,当然Handler里还有其他的方法供实现,有兴趣的可以去查API,这里不过多解释. 1. 定义一个Han

Android中Xposed框架篇---修改系统位置信息实现自身隐藏功能实例_Android

一.前言 本文主要来介绍一个实际案例就是如何通过这个框架来修改系统的地理位置信息来实现隐藏功能,在如今社交工具的发展特别是微信,他有一个实时位置共享功能,那么对于那些不是单身狗的同学来说可能会有些蛋疼,哪天媳妇要查岗发送位置,结果你不在她期望的位置这时候就尴尬了,而且朋友圈在分享内容的时候可以选择当前位置,有的屌丝就像我一样没钱但是又想到处旅游,那么这时候咋们就可以一本正经的装个逼了. 二.定位原理 看到上面说的那么多,感觉这个功能必须要搞起来了,好处太多了,下面咋们就开始操作了,但是在这之前一

Android中WebView实现点击超链接启动QQ的方法

前言 之前有次在面试的时候,面试官问了一个如何在WebView点击超链接启动类型QQ类似第三方应用,我当时的回答是用WebView与js交互可以做到.面试官听了没再说什么,应该是答案不是他期望的.今天发现原来可以这样实现,记录一下. 实现思路 在Web开发中,启动QQ来临时会话,可以通过一个URL链接 <a target="_blank" href="http://wpa.qq.com/msgrd?v=3&uin=748895431&site=qq&am

Android中发送Http请求(包括文件上传、servlet接收)的实例代码_Android

复制代码 代码如下: /*** 通过http协议提交数据到服务端,实现表单提交功能,包括上传文件* @param actionUrl 上传路径 * @param params 请求参数 key为参数名,value为参数值 * @param file 上传文件 */public static void postMultiParams(String actionUrl, Map<String, String> params, FormBean[] files) {try {PostMethod p

Android中CSS设置select高度的bug解决方法及jq操作select

用CSS设置select的height和line-height,在有的Android版本中无效,不过可以通过添加"-webkit-appearance: listbox;"属性解决这个BUG,完整实例代码如下: .styled-select {  -webkit-appearance: listbox;  width: 100%;  font-size: 36px;  display: inline-block;  height: 80px;  line-height: 80px;  

Android中发送Http请求(包括文件上传、servlet接收)的实例代码

复制代码 代码如下:/*** 通过http协议提交数据到服务端,实现表单提交功能,包括上传文件* @param actionUrl 上传路径 * @param params 请求参数 key为参数名,value为参数值 * @param file 上传文件 */public static void postMultiParams(String actionUrl, Map<String, String> params, FormBean[] files) {try {PostMethod po

Android中使用am命令实现在命令行启动程序详解_Android

在Android中,除了从界面上启动程序之外,还可以从命令行启动程序,使用的是命令行工具am. 复制代码 代码如下: usage: am [subcommand] [options]     start an Activity: am start [-D]         -D: enable debugging     send a broadcast Intent: am broadcast     start an Instrumentation: am instrument [flags