タイマータスクまたはハンドラー


103

10秒ごとになんらかのアクションを実行したいとしますが、必ずしもビューを更新する必要はありません。

問題は、次のようにtimertaskでtimerを使用する方が良い(つまり、より効率的で効果的)かどうかです。

final Handler handler = new Handler();

TimerTask timertask = new TimerTask() {
    @Override
    public void run() {
        handler.post(new Runnable() {
            public void run() {
               <some task>
            }
        });
    }
};
timer = new Timer();
timer.schedule(timertask, 0, 15000);
}

またはpostdelayedのハンドラー

final Handler handler = new Handler(); 
final Runnable r = new Runnable()
{
    public void run() 
    {
        <some task>
    }
};
handler.postDelayed(r, 15000);

また、どのアプローチをいつ使用するか、なぜそれらの1つが他の方法よりも効率的であるか(実際にそうである場合)について説明していただければ幸いです。


2
TimerTasksの不規則な動作に関する多くの投稿を読んだことがあります。私のアドバイスは、それらを回避し、ハンドラー/ postDelayedアプローチを使用することです。
Sound Conception

1
私はHandler-postDelayメソッドを使用したいと思います。より細かく制御でき、内側からスケジュールできます
mihail


TimerTaskはバックグラウンドタスクであるため、UIを更新できません。ただ言う...
Yousha Aleayoub

1
me..thanksのために働いていた
jyotsna

回答:


95

Handlerより良いですTimerTask

Java TimerTaskとAndroidのHandler両方を使用すると、バックグラウンドスレッドで遅延タスクと繰り返しタスクをスケジュールできます。ただし、文献ではAndroidでのHandleroverの使用を圧倒的に推奨してTimerTaskいます(ここここここここここここ、およびここを参照)。

TimerTaskで報告された問題のいくつかは次のとおりです。

  • UIスレッドを更新できません
  • メモリリーク
  • 信頼できない(常に機能するとは限らない)
  • 実行時間の長いタスクは、次にスケジュールされたイベントを妨害する可能性があります

私が見たあらゆる種類のAndroidの例の最良のソースはCodepathにあります。以下は、Handler繰り返しタスクの例です。

// Create the Handler object (on the main thread by default)
Handler handler = new Handler();
// Define the code block to be executed
private Runnable runnableCode = new Runnable() {
    @Override
    public void run() {
      // Do something here on the main thread
      Log.d("Handlers", "Called on main thread");
      // Repeat this the same runnable code block again another 2 seconds
      handler.postDelayed(runnableCode, 2000);
    }
};
// Start the initial runnable task by posting through the handler
handler.post(runnableCode);

関連した


6
@Reekいいえ、GCが処理します。ただし、遅延実行のためにポストされた実行可能ファイルを処理する必要があります。上記の例では、使用されるランナブルは内部クラスインスタンスなので、含まれているクラス(アクティビティである可能性があります)への暗黙的な参照を保持しています。ランナブルは、次の実行時まで、ハンドラーに関連付けられたルーパーのメッセージキューに留まります。次回の実行時は、コンテキストが無効で、含まれているクラスインスタンスがリークする可能性があります。このような参照mHandler.removeCallbacks(runnableCode)は、適切なタイミングで(たとえばonStop()、アクティビティに対して)使用してクリアできます。
bitbybit 2017年

7
これまでに参照を提示する最良の方法!!! (ここ、ここ、ここ、ここ、ここ、ここ、およびここを参照)。
iRavi iVooda 2018年

それをViewModel内で使用したい場合はどうなりますか?そこにandroidを持たないという理想に反していませんか?
desgraci

@desgraci、私はViewModelを使用していませんが、ドキュメントからは、ViewModelがビュー階層にアクセスしたり、ActivityまたはFragmentへの参照を含めたりしてはならないことがわかります。「Androidモノ」を持っていることを禁じているものは一般にありません。
Suragch

今日の時点では、これらの参照は時代遅れであり、考慮に入れるほど十分な情報はありません。上記の4つの欠点は、コードを不適切にプログラムした場合にのみ発生します。TimerTasksは、バックグラウンドで定期的に何かを実行し、何らかの条件が当てはまる場合は最終的にUIThreadで何かを実行したい場合、依然として非常に良い選択です。
デビッド

18

タイマーの使用にはいくつかの欠点があります

タスクを実行する単一のスレッドのみを作成し、タスクの実行に時間がかかりすぎると、他のタスクが影響を受けます。タスクによってスローされた例外を処理せず、スレッドが終了するだけで、他のスケジュールされたタスクに影響を与え、実行されることはありません

コピー元:

TimerTask vs Thread.sleep vs Handler postDelayed-Nミリ秒ごとに関数を呼び出すのが最も正確ですか?


6
では、ワンショットタスクの場合はどうでしょうか。メッセージキューのオーバーヘッドがないため、Timerの方が適しているように思われますか?
マイケル

2
私たちは決して知ることはないと思います
デニー

5

承認された回答のKotlinバージョン:

val handler = Handler()

val runnableCode = object : Runnable {
    override fun run() {
       Log.d("Handlers", "Called on main thread")
       handler.postDelayed(this, 2000)
    }
}

handler.post(runnableCode)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.