Kotlinで停止したタイマを再開できない時の解決方法

タイマは動かせます、停止もできます、けど再開できません…

こうした悩みを解決します。

本記事を通じてできるようになること

・タイマ使用時にエラーがでないよう設計する
・タイマON/OFFをボタン制御で切り替える
・タイマタスクで直接メインアクティビティのUI要素にアクセスする
・テキストビューの値が数値だけか判別する

サンプルプログラムはこちら

ソースコードも提供しています
サンプルプログラムのソースコードを見る

長くなりました、ではいきましょう。

結論:タイマは使う度に新たに作る必要がある

結論から先に言うと、タイマは使い捨てのスレッドです。

タイマは停止、再開という概念のものではなく、停止するときはタイマスレッドを破棄、再開したいときは新たに作り直しと考えます。

そのため、設計にあたってタイマ開始する直前にタイマオブジェクトを生成する必要があります。

こんな感じでタイマを開始させます。

 val timer = Timer() /*これが重要!*/
 timer.scheduleAtFixedRate(1000, 3000) {
     //do something
 }

一度だけタイマを実行するならつまずかないと思います。

開始したタイマを停止して再開したいときに問題が起こるんですね。

タイマ再開時にアプリが停止する問題

テキトーに関数作って引数のbool値でタイマの開始、停止を試みます。

val timer = Timer()

fun timerstart(flag:Boolean){
    if(flag == true) {
        timer.scheduleAtFixedRate(1000, 3000) {
            //do something
        }
    } else {
        timer.cancel()
    }
}

この処理だと1回目はタイマが正常動作しますが、2回目のタイマ動作をしようとした瞬間にアプリが落ちます。

関数外で作成したタイマオブジェクトに対して処理しているからです。

動作を考える

まず事前に定義しているval timer = Timer()でタイマオブジェクトができています。

そしてtrueを引数としてtimerstart関数をよんでタイマをスタートします。

上記は1秒のウェイトの後、3秒毎に処理を行うscheduleAtFixedRateメソッドを使っています。

タイマを止めるときはfalseを引数にtimerstart関数をよんでタイマが停止します。

ここまでは設計通りに動くはずです。

続いてタイマを再開しようとflag = trueで関数実行するとアプリが落ちます。

タイマ再開時に落ちる原因と対策

タイマは実は既存スレッドとは別のスレッドを作り、その中でタスクを実行しています。

なので、cancel()でタイマを停止するというのは、タイマスレッドを終了(=破棄)しているということになります。

タイマスレッドが終了して無くなっているのにタイマを再開しようとすると、タイマの実体がないのでアプリ側が処理できずに落ちてしまいます。

そのため、冒頭でも書きましたがタイマを開始する前にはタイマオブジェクトを作る必要があるのです。

タイマは再開するというより、タイマを作る→動かす→捨てる→タイマを作る→…を毎回繰り返していることになります。

val timer = Timer()

fun timerstart(flag:Boolean){
    if(flag == true) {
        timer = Timer() //作る
        timer.scheduleAtFixedRate(1000, 3000) { //動かす
            //do something
        }
    } else {
        timer.cancel() //捨てる
    }
}

追記:タイマからUI要素にアクセスすると落ちる問題と対策

タイマは独自のスレッドを作って動くので、アクティビティやフラグメントのUI要素に直接アクセスすると落ちます。

アクセスしたい場合は、runOnUiThreadメソッドを用いる必要があります。

サンプルプログラム提供中

タイマを用いてテキストビューの数値を1秒毎にインクリメントするプログラムを提供しています。

手っ取り早くタイマを動かしたいという方は下記からソースコードをダウンロードして使ってみてください。

サンプルプログラムのソースコードを見る

まとめ

タイマは使い捨てのスレッドです

タイマ開始直前にタイマオブジェクトを生成する必要があります(そうでないとアプリが落ちる)

▼不明点や作成依頼などあればこちらからどうぞ
立プロに問合せる

▼インスタやってます

 

立プロ

組込エンジニア⇒個人事業主
ITと連携したビジネス発展をサポートしています。
C,C#,JavaScript, Vue, PHP, VBA, GAS, Kotlinなど、扱う言語が増えゆく日々。

立プロをフォローする
Kotlin
立科プログラミング
タイトルとURLをコピーしました