参考:《极客学院》
第一个知识点
分析:要用timer实现一个计时器,就必须涉及到timertask,同时还要考虑到我们在实现动态展示时间变化的时候要动态的更新UI,这里就要用到线程,我们使用handler来完成任务,下面实现一个倒计时的计时器
UI:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="match_parent"
tools:context="com.jikexueyuan.counttime.MainActivity" >
<EditText
android:id="@+id/inputtime"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:ems="10" >
<requestFocus />
</EditText>
<Button
android:id="@+id/gettime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="获取倒计时时间" />
<TextView
android:id="@+id/time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<Button
android:id="@+id/starttime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="开始计时" />
<Button
android:layout_marginTop="10dp"
android:id="@+id/stoptime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="停止计时" />
</LinearLayout>
java:
package com.jikexueyuan.counttime;
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.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class MainActivity extends Activity implements OnClickListener{
private EditText inputet;
private Button getTime,startTime,stopTime;
private TextView time;
private int i = ;
private Timer timer = null;
private TimerTask task = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView(){
inputet = (EditText) findViewById(R.id.inputtime);
getTime = (Button) findViewById(R.id.gettime);
startTime = (Button) findViewById(R.id.starttime);
stopTime =(Button) findViewById(R.id.starttime);
time = (TextView) findViewById(R.id.time);
getTime.setOnClickListener(this);
startTime.setOnClickListener(this);
stopTime.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.gettime:
time.setText(inputet.getText().toString());//在Textview中显示时间
i = Integer.parseInt(inputet.getText().toString());
break;
case R.id.starttime:
startTime();
break;
case R.id.stoptime:
stopTime();
break;
default:
break;
}
}
/**
*嗯,这里应该是最最关键的,开启线程来更新主UI
*/
private Handler mHandler = new Handler(){
public void handleMessage(Message msg) {
time.setText(msg.arg1+"");
startTime();//不断的循环更新显示
};
};
public void startTime(){
timer = new Timer();//通过该实例执行schedule方法执行任务
task = new TimerTask() {
@Override
public void run() {
i--;
Message message = mHandler.obtainMessage();
message.arg1 = i;
if(i==){
stopTime();
}
mHandler.sendMessage(message);
}
};
timer.schedule(task, );//schedule方法有两种,我们使用这种只有两个参数的,注意第二个参数的意思,1代表1ms,1000代表1s变化一次
}
public void stopTime(){
timer.cancel();//取消任务
}
}
像这种举一反三,了解到怎么更新UI的原理就比较好办了,还有就是实现的原理就是通过自己输入的参数进行变化,当然可以随意发挥了,比如在不输入参数的情况下,顺序计时,那就将i从0开始加呗,直到手动停止才停止就OK了。
第二个知识点
安卓内部提供了非常多的API,于是找找有没有计时器的控件,嗯,没错,找到了,那就是Chronometer,下面简单的解释一下用法
UI
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="match_parent" >
<Chronometer
android:id="@+id/choronometer"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<Button
android:id="@+id/start"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="开始计时"
/>
<Button
android:id="@+id/stop"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="停止计时"
/>
<Button
android:id="@+id/again"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="重置"
/>
</LinearLayout>
</LinearLayout>
java
注意setBase(long base) //设置倒计时定时器
setFormat(String format) //设置显示时间的格式
start() //开始计时
stop() //停止计时
setOnChronometerTickListener(Chronometer.OnChronometerTickListener listener) //当计时器改变时调用
package com.example.countime2;
import android.app.Activity;
import android.os.Bundle;
import android.os.SystemClock;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Chronometer;
public class MainActivity extends Activity implements OnClickListener {
private Chronometer chronometer=null;
private Button startbtn,stopbtn,againbtn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
chronometer=(Chronometer) findViewById(R.id.choronometer);//果然很简单
chronometer.setFormat("计时:%s");//设定显示的格式
startbtn.setOnClickListener(this);
stopbtn.setOnClickListener(this);
againbtn.setOnClickListener(this);
}
@Override
public void onClick(View v){
switch (v.getId()) {
case R.id.start:
chronometer.start();//人家已经做好了方法
break;
case R.id.stop:
chronometer.stop();
break;
case R.id.again:
chronometer.setBase(SystemClock.elapsedRealtime());//这个方法要看看后面的解释
default:
break;
}
}
}
总结:关键还是在handler那里的更新UI,什么时候使用what字段,什么时候使用arg1,arg2字段
- 如果一个Message只需要拼带简单的int型信息,应优先使用Message.arg I和Message.arg2属性来传递信息,这比用Bundle更节省内存。 尽可能使用Message.what来标识信息,以便用不同方式处理Message.*