最近才开始工作,总感觉没有做出什么东西,也没有学到很多东西,之前想学学大神总结知识点,但有没那耐心,而且其中遇到的问题也比较多,但又不能什么都不做,所以从现在开始就把在工作中遇到的一些问题和方法记录下来,做个备忘和分享,如有错误,还请大家指正。
实现原理:
使用获取handler对象,复写其handleMessage方法,然后在其run方法中每隔一秒发送一次空消息,然handler不断地接收并处理该消息,其中的暂停和开始是通过一个boolean类型的标签来控制的,注意的是,要首先发送一个该类型的空消息来来让handler进入消息的处理机制开始sendEmptyMessageDelayed(1, 1000);进行循环发送。
废话不多说,直接上代码:
MainActivity代码:
package com.ygc.handlertimer;
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.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity implements OnClickListener{
Button mStartBtn,mStopBtn;
TextView mTimeTextView;
Handler mHandler;
boolean isStart;
long timeMinute;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mStartBtn = (Button) findViewById(R.id.btn_start);
mStopBtn = (Button) findViewById(R.id.btn_stop);
// 记得为按钮设置监听哦
mStartBtn.setOnClickListener(this);
mStopBtn.setOnClickListener(this);
mTimeTextView = (TextView) findViewById(R.id.show_time);
// 模拟定时5分钟
timeMinute = 5 * 60 * 1000;
// 在主线程中创建的handler本身就属于主线程,但是不指定的话,handler下会有警告的标注线
mHandler = new Handler(getMainLooper()){
@Override
public void handleMessage(Message msg) {
if (msg.what == 1) {
if (timeMinute > 0) {
if (isStart) {
timeMinute -= 1000;
mTimeTextView.setText(""+timeMinute);
Log.e("MainActivity", timeMinute+"");
/*如果实在其他子线程中进行的UI刷新操作,可以获取到主线程的handler之后,
使用runOnUiThread来刷新UI操作*/
// mHandler.post(new Runnable() {
// @Override
// public void run() {
//// 可以在这做相关的数据处理,昨晚数据处理使用runOnUiThread刷新主线程UI
// runOnUiThread(new Runnable() {
// @Override
// public void run() {
// mTimeTextView.setText(""+timeMinute);
// }
// });
// }
// });
}
// 每隔一秒发送一次消息
sendEmptyMessageDelayed(1, 1000);
}
}
}
};
// 记得要发送消息之后,handler才能接收到消息,进行处理;
mHandler.sendEmptyMessage(1);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_start:
isStart = true;
break;
case R.id.btn_stop:
isStart = false;
break;
default:
break;
}
}
}
布局文件代码:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.ygc.handlertimer.MainActivity" >
<Button
android:id="@+id/btn_stop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/btn_start"
android:layout_alignBottom="@+id/btn_start"
android:layout_toRightOf="@+id/show_time"
android:text="结束计时" />
<Button
android:id="@+id/btn_start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginRight="14dp"
android:layout_toLeftOf="@+id/show_time"
android:text="开始计时" />
<TextView
android:id="@+id/show_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="78dp"
android:text="time"
android:textSize="30sp" />
</RelativeLayout>
运行这种方法后发现线程子开启后就一直没有关闭,比较消耗性能,所以就在后面的按钮中加了判断,将线程的延迟发送消息移到了计时操作的内部,这样在按钮点击时才进行消息发送开启计时,避免了handler消息的一直发送。
下面是修改后的代码:
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.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity implements OnClickListener{
Button mStartBtn,mStopBtn;
TextView mTimeTextView;
Handler mHandler;
boolean isStart;
long timeMinute;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mStartBtn = (Button) findViewById(R.id.btn_start);
mStopBtn = (Button) findViewById(R.id.btn_stop);
// 记得为按钮设置监听哦
mStartBtn.setOnClickListener(this);
mStopBtn.setOnClickListener(this);
mTimeTextView = (TextView) findViewById(R.id.show_time);
// 模拟定时5分钟
timeMinute = 5 * 60 * 1000;
// 在主线程中创建的handler本身就属于主线程,但是不指定的话,handler下会有警告的标注线
mHandler = new Handler(getMainLooper()){
@Override
public void handleMessage(Message msg) {
if (msg.what == 1) {
if (timeMinute > 0) {
if (isStart) {
sendEmptyMessageDelayed(1, 1000);
timeMinute -= 1000;
mTimeTextView.setText(""+timeMinute);
Log.e("MainActivity", timeMinute+"");
/*如果实在其他子线程中进行的UI刷新操作,可以获取到主线程的handler之后,
使用runOnUiThread来刷新UI操作*/
// mHandler.post(new Runnable() {
// @Override
// public void run() {
//// 可以在这做相关的数据处理,昨晚数据处理使用runOnUiThread刷新主线程UI
// runOnUiThread(new Runnable() {
// @Override
// public void run() {
// mTimeTextView.setText(""+timeMinute);
// }
// });
// }
// });
}
// 每隔一秒发送一次消息
// sendEmptyMessageDelayed(1, 1000);
}
}
}
};
// 记得要发送消息之后,handler才能接收到消息,进行处理;
mHandler.sendEmptyMessage(1);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_start:
if (!isStart) {
mHandler.sendEmptyMessage(1);
isStart = true;
}
break;
case R.id.btn_stop:
if (isStart) {
mHandler.removeMessages(1);
isStart = false;
}
break;
default:
break;
}
}
}