MY_GEEK_計時器的timer實現

飄過的小熊發表於2016-05-20

參考:《極客學院》

第一個知識點

分析:要用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 = 0;
    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==3){
                    stopTime();
                }
                mHandler.sendMessage(message);
            }
        };
        timer.schedule(task, 1000);//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.*

相關文章