1. 程式人生 > >如何在一個Activity中,開啟多個計時器

如何在一個Activity中,開啟多個計時器

最近要做這麼一個東西,在一個activity中,實現多個計時器,點選哪個按鈕,就開啟哪個計時器。如下圖:
這裡寫圖片描述

涉及執行緒操作、更新ui。看著好簡單,做起來還真花我不少功夫,主要是沒理清這個思路,所以寫程式碼的時候,先設計好真的很重要!!!寫在部落格裡,讓困惑的同學少走彎路吧,也給我提個醒,寫程式碼先設計,想想行的通不。

主要是這麼一個問題:每點Button的時候,就開啟一個執行緒進行倒計時這種耗時操作(這思路其實有問題),再點其他倒計時按鈕的時候就出問題了,每多點一次,倒計時速度就加快了。在這個問題困擾很久。。。因為點選倒計時按鈕,主開啟一個子執行緒,再點選倒計時按鈕,就會在子執行緒中開啟一個子執行緒,從而倒計時速度加快,明白了這個,實現這個功能就不是啥問題了。

最終的解決思路是,只開啟一次子執行緒,每次點選按鈕的時候,我只改變倒計時的時間就好了。當然把這個時間設定成全域性的。
我繞了路,通過service實現了,其實一個activity就夠了。
貼出程式碼:
xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools
="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.myself.timer2.MainActivity">
<LinearLayout android:id="@+id/ll_clock" android:layout_width="match_parent" android:layout_height
="200dp" android:background="#737373">
<TextView android:id="@+id/tv_clock" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:text="00:00" android:textColor="#ffffff" android:textSize="80dp" /> </LinearLayout> <LinearLayout android:id="@+id/ll_layout1" android:layout_below="@+id/ll_clock" android:layout_width="match_parent" android:layout_height="wrap_content"> <Button android:onClick="onClick" android:id="@+id/btn_03" android:layout_weight="1" android:text="3分鐘" android:layout_width="1dp" android:layout_height="wrap_content" /> <Button android:onClick="onClick" android:id="@+id/btn_05" android:text="5分鐘" android:layout_weight="1" android:layout_width="1dp" android:layout_height="wrap_content" /> </LinearLayout> <LinearLayout android:layout_below="@+id/ll_layout1" android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:onClick="onClick" android:id="@+id/btn_10" android:layout_weight="1" android:text="10分鐘" android:layout_width="1dp" android:layout_height="wrap_content" /> <Button android:onClick="onClick" android:id="@+id/btn_15" android:text="15分鐘" android:layout_weight="1" android:layout_width="1dp" android:layout_height="wrap_content" /> </LinearLayout> </RelativeLayout>

activity

package com.example.myself.timer2;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Handler;
import android.os.IBinder;
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.Button;
import android.widget.Switch;
import android.widget.TextView;

import org.w3c.dom.Text;

import java.lang.ref.WeakReference;

public class MainActivity extends AppCompatActivity implements View.OnClickListener,ServiceConnection{

    private Button mBtn_03,mBtn_05,mBtn_10,mBtn_15;
    private  TextView mTv_click;
    Intent intent;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initView();
    }

    @Override
    protected void onDestroy() {
        stopService(intent);
        super.onDestroy();
    }

    private void initView() {
        mBtn_03 = findViewById(R.id.btn_03);
        mBtn_05 = findViewById(R.id.btn_05);
        mBtn_10 = findViewById(R.id.btn_10);
        mBtn_15 = findViewById(R.id.btn_15);
        mTv_click = findViewById(R.id.tv_clock);
    }

    public void onClick(View v) {
        switch(v.getId()){
            case R.id.btn_03:
                intent =new Intent(this, MyService.class);
                intent.putExtra("second",3*60);
                bindService(intent,MainActivity.this,BIND_AUTO_CREATE);
                startService(intent);
                break;
            case R.id.btn_05:
                intent = new Intent(this,MyService.class);
                intent.putExtra("second",5*60);
                bindService(intent,MainActivity.this,BIND_AUTO_CREATE);
                startService(intent);
                break;
            case R.id.btn_10:
                intent = new Intent(this,MyService.class);
                intent.putExtra("second",10*60);
                bindService(intent,MainActivity.this,BIND_AUTO_CREATE);
                startService(intent);
                break;
            case R.id.btn_15:
                intent = new Intent(this,MyService.class);
                intent.putExtra("second",15*60);
                bindService(intent,MainActivity.this,BIND_AUTO_CREATE);
                startService(intent);
                break;
        }
    }


    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        MyService.Binder binder = (MyService.Binder) service;
        MyService myService = binder.getService();
        myService.setCallback(new MyService.Callback() {
            @Override
            public void onDataChange(int data) {
                Message msg = new Message();
                msg.obj = data;
                handler.sendMessage(msg);
            }
        });
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {

    }

    private Handler handler = new Handler() {
        int min = 0;
        int sec = 0;
        int count = 0;
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            count = Integer.valueOf(msg.obj.toString());
            sec = count % 60;
            min = count / 60;
            mTv_click.setText(String.format("%1$02d:%2$02d", min, sec));
            Log.e("handleMessage: ", msg.obj.toString() + "");
        }
    };
}

service

package com.example.myself.timer2;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.util.Log;

import static android.hardware.Sensor.TYPE_ORIENTATION;

/**
 * Created by Administrator on 2018/3/12.
 */

public class MyService extends Service  {

    private boolean connecting = false;
    private Callback callback;
    private int second = 0;
    public class MyRunnable implements Runnable{

        @Override
        public void run() {
            while (connecting == true ) {
                if (second > 0){
                    second--;
                    if (callback != null) {
                        callback.onDataChange(second);
                    }
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    /**
     * 以startService方式啟動的時候呼叫
     * @param intent
     * @param flags
     * @param startId
     * @return
     */
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        second = intent.getIntExtra("second",0);
        return START_STICKY;//統有足夠多資源的時候,就會重新開啟service,保證後臺執行
    }

    /**
     * 其他元件以bind方式啟動的時候呼叫
     * 用來和其他元件互動
     *
     * @param intent
     * @return IBinder介面,這個介面是和其他元件互動的橋樑
     *          如果service沒有繫結元件,則返回為null
     */
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return new Binder();
    }



    public class Binder extends android.os.Binder {
        public MyService getService() {
            return MyService.this;
        }
    }

    /**
     * service開啟的時候呼叫
     * 只調用一次
     */
    @Override
    public void onCreate() {
        new Thread(new MyRunnable()).start();
        super.onCreate();
        connecting = true;
    }

    public void setCallback(Callback callback) {
        this.callback = callback;
    }

    public static interface Callback {
        void onDataChange(int data);
    }

    @Override
    public void onDestroy() {
        /**
         * 釋放資源
         */
        super.onDestroy();
        connecting = false;
    }
}