android处理程序 - 好的,计时器 - 不幸停止了。差异为何?

时间:2015-11-24 06:56:27

标签: android multithreading debugging timer handler

我正在使用Android Studio和模拟器​​android 4.1.2。 我的代码

    Timer timer = new Timer ();
    timer.schedule(new TimerTask() {
        @Override
        public void run() {
            myRun();
        }
    },10000,10000);

导致“不幸的是,app停止了”,但我发现了代码

    Handler handler = new Handler();
    handler.postDelayed(new Runnable() {
        public void run() {
            myRun();
        }
    }, 2000);

运行正常并按我的预期显示。 两者之间的内在差异是什么?

P.S。

public void myRun () {
    myView.removeAllViews();
    drawView = new DrawView(myContext, myView);
    myView.addView(drawView);
}

我正在尝试永久更新自定义视图,直到用户取消它。只需循环

while (myRun) {

导致模拟器甚至无法响应甚至后退按钮,在第二个线程中运行该更新

new Thread(new Runnable() {
        @Override
        public void run() {
            while (myRun) {

                myView.post(new Runnable() {
                    public void run() {
                        myView.removeAllViews();
                        drawView = new DrawView(myContext, myView);
                        myView.addView(drawView);
                    }
                });

            }
        }
    }).start();

结果相同(有趣的是,如果我在第二个线程中运行带有断点的调试,屏幕更新,因为我预期很多次,但运行w / out调试不会更新屏幕)。

3 个答案:

答案 0 :(得分:0)

Timer在一个单独的线程上执行其任务,该线程仅用于提供由此特定计时器创建的任务。 Handler在其Looper的线程上运行其任务,该线程可能是也可能不是UI线程。一般来说,如果在单独的线程上使用Handler,这两个类之间没有太大区别。但在Android中使用Handler和HandlerThread更为常见。

如果您需要与用户界面进行互动,最好使用Handler

答案 1 :(得分:0)

您可以在这里找到答案:Handler vs Timer

去看看吧。 :)

答案 2 :(得分:0)

这是一个有趣的问题和答案在于android遵循的线程/ GUI策略。

众所周知,UI在主线程上运行。 Timer创建一个不同的线程,android不允许在不同的线程中更新UI。为什么呢?

假设您已经在活动中启动了一个更新TextView的线程,并且在线程运行时您移动到其他应用程序。现在,主线程不再存在,当另一个线程尝试更新TextView时,它无法找到TextView。结果,我们看到了崩溃。

现在让我来看看TimerTask和Handler之间的区别。

TimerTask创建一个新线程,等待指定的时间,然后在同一个线程中执行run()方法。另一方面,Handler创建一个新线程,等待指定的持续时间然后返回主线程并在MAIN线程上执行run()方法(如果处理程序在主线程上)。因此,它工作正常。

但是你也可以用计时器来做。 请参阅以下代码:

final Runnable setRunnable = new Runnable() {
    public void run() {
         myView.removeAllViews();
         drawView = new DrawView(myContext, myView);
         myView.addView(drawView);
    }
};

TimerTask task = new TimerTask(){
    public void run() {
        getActivity().runOnUiThread(setRunnable);
    }
};

Timer timer = new Timer();
timer.schedule(task, 1000);

在此主题中,您将设置一个runnable,以便在计时器的持续时间后在UI线程上运行。