如何在一個Activity中,開啟多個計時器
阿新 • • 發佈:2019-02-19
最近要做這麼一個東西,在一個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;
}
}