Timertask或Handler


103

假设我想每隔10秒执行一次操作,而不必更新视图。

问题是:将timer与timertask一起使用会更好(我的意思是更有效):

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);
}

或只是带有延迟的处理程序

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

同样,如果您能解释何时使用哪种方法以及为什么其中一种方法比另一种方法更有效(如果确实如此),我将不胜感激。


2
我读过许多有关TimerTasks异常行为的文章。我的建议是避免使用它们,并使用handler / postDelayed方法。
音效概念

1
我更喜欢Handler-postDelay方法-您拥有更多控制权,并且可以从内部安排它
mihail 2013年


TimerTask是一个后台任务,因此您无法更新UI。只是说...
Yousha Aleayoub

1
为我工作..谢谢
jyotsna

Answers:


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应该照顾它。但是您需要照顾发布的可运行项,以免延迟执行。在上面的示例中,所使用的runnable是一个内部类实例,因此持有对包含类(可能是活动)的隐式引用。可运行对象将保留在处理程序的关联循环程序的消息队列中,直到其下一次执行时间为止(该时间可能是在上下文无效之后并且可能泄漏包含的类实例)。您可以通过mHandler.removeCallbacks(runnableCode)在适当的时间使用(例如onStop()活动)来清除此类引用。
bitbybit

7
提出参考文献的最佳方式!!!(请参见此处,此处,此处,此处,此处和此处)。
iRavi iVooda

如果我想在ViewModel中使用它呢?不反对在那里没有Android设备的理想吗?
desgraci

@desgraci,我没有使用过ViewModel,但是从文档中我只看到它说ViewModel不应访问视图层次结构,也不应包含对Activity或Fragment的引用。我看不到一般禁止使用“ Android事物”的任何东西。
Suragch

到今天为止,这些引用对我来说已经过时了,不足以供参考。仅当您对代码进行严重编程时,列出的这4个缺点才是真实的。如果要在后台定期运行某些内容,并在某些情况下最终在UIThread上运行某些内容,则TimerTasks仍然是一个很好的选择。
大卫,

18

使用计时器有一些缺点

它仅创建一个线程来执行任务,并且如果一个任务花费的时间太长,则其他任务会受到影响。它不处理任务引发的异常,线程只是终止,这会影响其他计划的任务,并且它们永远不会运行

复制自:

TimerTask与Thread.sleep与Handler postDelayed-每N毫秒调用一次函数最准确?


6
那么一次完成任务呢?听起来,也许Timer对此更好,因为您没有消息队列的开销?
迈克尔

2
我想我们永远不会知道
Denny

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)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.