Androidのカウントダウン

# はじめに
Androidアプリでカウントダウン機能を実装するのに使えるクラスを紹介していきます。AndroidStudioの使い方に慣れていない方向けに記事を書いています。カウントダウンのコードだけ知りたい方はページの最後をご覧ください。

今回は、CountDownクラスを作って、

- 毎秒の処理
- 終わった時の処理

を後からつけられるようにしていきます。

# リスナーを作る
リスナーって何？という方もとりあえず、次の二つのファイルを作ってください。これがあるおかげで今回のカウントダウンクラスは汎用性が上がります。

<img width="300" alt="override_method" src="https://qiita-image-store.s3.amazonaws.com/0/90254/385e57e2-06d4-18ea-893b-56dddd733505.png">

<img width="560" alt="override_method" src="https://qiita-image-store.s3.amazonaws.com/0/90254/59485377-70b4-0b5c-f525-551f00c9c4a2.png">

上のような状態で、下で紹介したようなファイルを２つ作ってください。

```OnFinishListener.java
public interface OnFinishListener {
    void onFinish();
}
```


```OnTickListener.java

public interface OnTickListener {
    void onTick(long millisUntilFinished);
}
```

以上でリスナーは作り終わりました。

- [【Java】interfaceについて](http://qiita.com/rild/items/94b5adeff1cdfbd8a973)

# CountDownクラスの準備

作っていくCountDownクラスは、 **合計時間は何秒にするか** と **一定間隔の処理を何秒毎に実行するか** を指定する必要があります。

さらに今回は、**リスナー** を作ることでCountDownクラスの中には **具体的な処理は書かない** ようにしていきます。

まず、CountDownクラスを作ってください。

<img width="560" alt="override_method" src="https://qiita-image-store.s3.amazonaws.com/0/90254/e817b2c9-ad60-b448-c366-831825880f78.png">

<img width="560" alt="override_method" src="https://qiita-image-store.s3.amazonaws.com/0/90254/c922f2ee-7894-9a24-95fb-8a540e4c3bb0.png">

## リスナーを入れる変数を宣言する

```CountDown.java
public class CountDown extends CountDownTimer {
    // CountDownクラスにリスナを宣言する
    OnFinishListener onFinishListener;
    OnTickListener onTickListener;

    // この後の処理を書いて行く
}
```

## メソッド, コンストラクタを作る

作ったクラスにメソッドを書いていきます。
CountDownクラスには

- 終わった時に実行する実行する処理
- ある一定時間毎に実行する処理

が必要になります。

| メソッド名 | 内容 |
| :-------------| :------------- |
|  onTick  | ある一定時間毎に実行する処理    |
|  onFinish|  終わった時に実行する実行する処理    |

これに加えて、CountDownクラスの

- 何秒数えるか
- 何秒おきに数えるか

という値を初期化する必要があります。初期化はコンストラクタで行っていきます。

AndroidStudio では control + O を押すと楽ができます。

<img width="440" alt="override_method" src="https://qiita-image-store.s3.amazonaws.com/0/90254/9759c161-7b69-2802-28ee-fa7fd84c3a2c.png">


```CountDown.java
public class CountDown extends CountDownTimer {
    public CountDown(long millisInFuture, long countDownInterval) {
        super(millisInFuture, countDownInterval);
    }

    @Override
    public void onTick(long millisUntilFinished) {
        //毎秒呼ばれる (呼ばれる間隔は指定することができる)
    }

    @Override
    public void onFinish() {
        //数え終わった時に呼ばれる
    }
}
```


カウントダウンが終了したらリスナーに登録された処理が実行されるようにしていきます。

onFinishメソッドを書いていきます。

```CountDown.java
@Override
public void onFinish() {
    //数え終わった時に呼ばれる
    if (onFinishListener != null) onFinishListener.onFinish();
}
```

onFinishメソッドと同様にonThickメソッドの中身を書いていきます。

```CountDown.java
@Override
public void onTick(long millisUntilFinished) {
    //毎秒呼ばれる (呼ばれる間隔は指定することができる)
    if (onTickListener != null) onTickListener.onTick(millisUntilFinished);
}
```

# 準備完了

カウントダウンするためのクラスが出来上がりました。以下の３つのファイルができていれば、準備完了です。


```OnFinishListener.java
public interface OnFinishListener {
    void onFinish();
}
```


> カウントダウンが終わったイベントを受けて、`onFinish` メソッドを実行できるようにする `interface`



```OnTickListener.java
public interface OnTickListener {
    void onTick(long millisUntilFinished);
}
```


> 毎秒のイベントを受けて、`onTick` メソッドを実行できるようにする `interface`


```CountDown.java
public class CountDown extends CountDownTimer {

    //ここにリスナーを入れるための変数を宣言する
    OnFinishListener onFinishListener;
    OnTickListener onTickListener;

    public CountDown(long millisInFuture, long countDownInterval) {
        super(millisInFuture, countDownInterval);
    }

    @Override
    public void onTick(long millisUntilFinished) {
        //毎秒呼ばれる (呼ばれる間隔は指定することができる)
        if (onTickListener != null) onTickListener.onTick(millisUntilFinished);
    }

    @Override
    public void onFinish() {
        //数え終わった時に呼ばれる
        if (onFinishListener != null) onFinishListener.onFinish();
    }

    public void setOnFinishListener(OnFinishListener onFinishListener) {
        this.onFinishListener = onFinishListener;
    }

    public void setOnTickListener(OnTickListener onTickListener) {
        this.onTickListener = onTickListener;
    }
}
```

> カウントダウンをするクラス。使うのはこれ。

# 実装する
Android のプロジェクトを新規作成して、`MainAcitivity`でカウントダウン機能を実装してみます。

## 変数の宣言とインスタンスの生成
```MainActivity.java
//変数の宣言
CountDown countDown;

//インスタンスの生成
countDown = new CountDown(3000, 100);
```
まずは、インスタンスの生成です。

CountDownのコンストラクタの引数には

| 型 | 変数名 |
| :------------- | :------------- |
| long      | millisInFuture     |
| long      | countDownInterval   |

の２種類が定義されています。

millisInFuture はカウントダウンする時間 (onFinishが呼ばれるまでの時間 )です
上の例では3000と与えているので、3秒 (3000ミリ秒) になります。

countDownInterval はカウントダウンしている時に、何秒おきに onTick が呼ばれれるかを決める値です。
上の例では100と与えているので、0.1秒 (100ミリ秒) 毎に onTick メソッドが呼ばれます。


> 注) ただ、ログなどで確認してみるとわかりますが、厳密に100ミリ秒というわけではないので、厳密なものが欲しい場合には工夫が必要になると思います。

## onTickとonFinishメソッドの定義

CountDownクラスの変数として用意した onFinishListener と OnTickListener それぞれのインスタンスを匿名クラスで与えてやります。

```MainActivity.java
        countDown.setOnFinishListener(new OnFinishListener() {
            @Override
            public void onFinish() {
                //カウントダウン終了時の処理
                timeText.setText(String.valueOf(0));
                Toast.makeText(getApplicationContext(), "カウント終了" , Toast.LENGTH_SHORT).show();
            }
        });
```
カウントダウン終了時にToastでメッセージを出してみました。

```MainActivity.java
        countDown.setOnTickListener(new OnTickListener() {
            @Override
            public void onTick(long millisUntilFinished) {
                //カウントダウン中の処理
                timeText.setText(String.valueOf(millisUntilFinished));
            }
        });
```
Toastだとイベントを捌き切れないので、TextViewクラスの変数textViewがあると仮定して、そこにミリ秒を表示させてみています。

## start!
以上の設定をして、countDownに対して、start()を呼べば処理が実行されます。

```MainActivity.java
countDown.start();
```

# 最後に
また今度、ストップウォッチ的なアプリのメイキング載せてみようと思います。