Android通过子线程和handler实现倒计时,可以开始暂停倒计时

时间:2021-04-30 10:15:04

Android通过子线程和handler实现倒计时,可以开始暂停倒计时

布局如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:paddingLeft="@dimen/activity_horizontal_margin"
    android:orientation="vertical"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="开始和暂停倒计时"
        android:onClick="btnDaoJiShi"/>
    <TextView android:text="10秒\n倒计时" android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:textSize="90sp"
        android:id="@+id/textView"/>
</LinearLayout>



代码如下:

package tech.androidstudio.handlerdemotimer;

import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity implements Runnable {
private Handler mainHandler;
    private TextView mTextView;
    private Thread mThread;
    private boolean mflag;
    private int mCount=10;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //主线程的 handler 接收到 子线程的消息,然后修改TextView的显示
        mainHandler=new Handler(){
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                int what = msg.what;
                switch (what){
                    case 1:
                        int arg1 = msg.arg1;
                        Log.d("Kodulf","Handler arg1="+arg1);
                        Log.d("Kodulf", "TestView  =" + mTextView.getText().toString());
                        mTextView.setText(String.valueOf(arg1));
                        break;
                }
            }
        };

        mTextView=(TextView)findViewById(R.id.textView);

        //子线程的初始化
        mThread = new Thread(this);
    }

    //TODO 这里才是最关键的部分:首先判断子线程是否是活动的状态,
    //TODO 如果不是活动的话,就是开始计时器或者重启计时器
    //TODO 如果是活动的话,就是暂停计时器。
    public void btnDaoJiShi(View view) {
        Log.d("Kodulf","mThread state"+mThread.getState());
        Log.d("Kodulf","mThread toString"+mThread.toString());

        if(!mThread.isAlive()){
            //开始计时器或者是重启计时器,设置标记为true
            mflag=true;
            //判断是否是第一次启动,如果是不是第一次启动,那么状态就是Thread.State.TERMINATED
            //不是的话,就需要重新的初始化,因为之前的已经结束了。
            //并且要判断这个mCount 是否为-1,如果是的话,说名上一次的计时已经完成了,那么要重新设置。
            if(mThread.getState()==Thread.State.TERMINATED){
                mThread = new Thread(this);
                if(mCount==-1) mCount=10;
                mThread.start();
            }else{
                mThread.start();
            }
        }else {
            //暂停计时器,设置标记为false
            mflag=false;
            //不可以使用 stop 方法,会报错,java.lang.UnsupportedOperationException
            //mThread.stop();
        }
    }

    @Override
    public void run() {
        //子线程必须要设置这个标记mflag和倒计时数。
        while(mflag&&mCount>=0){
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //每间隔 一秒钟 发送 一个Message 给主线程的 handler让主线程的hanlder 来修改UI
            //注意 这里的 message可以是通过obtain来获取 这样节省内存,它会自动的看有没有可以复用的,就不重复创建了
            Message message = Message.obtain();
            message.what=1;
            message.arg1=mCount;
            mainHandler.sendMessage(message);
            Log.d("Kodulf","mCount="+mCount--);
        }
    }

    //一定记住了要在onDestroy方法里面停止线程,这里数字小看不出来,如果在其他的地方可能就会影响性能了
    @Override
    protected void onDestroy() {
        super.onDestroy();
        mflag=false;
    }
}



代码:Anroid子线程 handler 实现倒计时的功能