【问题标题】:Replacing CountDownTimer with Handler and Runnable for better performance用 Handler 和 Runnable 替换 CountDownTimer 以获得更好的性能
【发布时间】:2018-09-03 15:03:15
【问题描述】:

我有基于 CountDownTimer 的游戏,它不断重复倒计时。此 countDown 正在计算用户对与 number 相关的某些操作做出反应的时间,如果用户反应 onFinish() 由一些 clickListener 调用,或者如果时间到了则由其自身调用。取决于succesCondition(),方法successfail 被调用,这些方法定义游戏是否仍在运行。

创建时

loop = gameLoop(time).start();

主活动

public CountDownTimer gameLoop(int time){
    return new CountDownTimer(time, time+100) {
        @Override
        public void onTick(long millisUntilFinished) {

        }

        @Override
        public void onFinish() {
            if (!Conditions.succesCondition(number)) {
                success();
            } else {
                fail();
            }
        }
    };
}

public void success() {
    loop.cancel();
    scoreCount++;
    animation.start();
}

public void fail(){
   loop.cancel();
}

但是,这个计时器在主线程上运行,并且提供了众所周知的问题skipped xx frames, your app might be doing too much work on its main thread,我发现这是CountDownTimer 的常见问题,用Handler 替换它是一个解决方案。

我不能把这个计时器放在AsyncTask 中,因为它主要在success() 方法中执行与 UI 相关的任务(TextViews、TextSwitcher、一些进度条等。我没有把它放在这些方法的代码中以更简洁主要问题的观点。我正在尝试使用处理程序重建 CountDownTimer- 类似的概念,并且可以运行以替换我的计时器,但实际上我什么也没有。如您所见,我只使用 onFinish 方法, onTick 不是必需的。

【问题讨论】:

  • 执行与 countDownTimer 行为相似的处理程序并不容易
  • 不,我不知道,我以前看过 countDownTimer 类,但我不知道如何自己重写它
  • 那么Handler 有什么不清楚的地方吗?哪些方法调用难以理解?
  • 不是说不清楚,但如果我只是通过重写计时器类来做到这一点,那么性能不会有任何差异
  • so CountDownTimer 不是罪魁祸首,但您的 onTick 方法在 UI 线程上做了太多工作

标签: java android countdowntimer android-handler


【解决方案1】:

好的。我终于想出了如何用处理程序处理它(呵呵):

public void startGameAction() {

    //My game actions

    handler = new Handler();
    runnable = () -> {
        if (!Conditions.succesCondition(number)) {
            success();
        } else {
            fail();
        }
    };
    handler.postDelayed(runnable,time);
}

public void success(){
        handler.removeCallbacks(runnable);
        handler = null;

        scoreCount++;
        //other stuff
        startGameAction();
    }

 private void fail() {
    handler.removeCallbacks(runnable);
    //other stuff
}

onCreate 仅 startGame 调用、handler 和 runnable 定义为类字段

startGameAction();

【讨论】:

    【解决方案2】:

    您可以使用AsyncTask 以及覆盖onProgressUpdate 方法来处理这种情况。

    这里是an example,关于如何实现与AsyncTask 的主线程交互的行为。该示例显示了下载的更新,可以轻松地将其转换为您的特定计时器问题。

    更新

    在我的情况下,几乎所有代码都在 onProgressUpdate 中,是吗? 还有意义吗?

    不,您的代码不会在onProgressUpdate 中。 onProgressUpdate 方法只会在你的 UI 中更新你的计时器。据我所知,成功和失败也将基于用户操作触发。然后触发这些操作,您也可以停止AsyncTask 以更新您的计时器。您只需要AsyncTask 不时更新计时器值。

    AsyncTask 结束时,您将在Activity 中收到回调。请参阅上面示例中的 mNotificationHelper.completed(); 函数。当计时器结束时,当您在Activity 中收到通知时,您可能会在那里执行以下任务。

    public void completed()    {
        if (!Conditions.succesCondition(number)) {
            success();
        } else {
            fail();
        }
    }
    

    【讨论】:

    • 在我的例子中,几乎所有代码都在 onProgressUpdate 中,它还有意义吗?
    • 不仅计时器与 UI 线程有关,我还有动画、textViews 等,它们会在每 3 秒重复一次的倒计时时更新
    • 是的,需要在onProgressUpdate更新倒计时相关的内容。
    【解决方案3】:

    我建议使用java.util.Timerjava.util.TimerTaskActivity.runOnUiThread() 的组合。首先创建一个Timer 并调用它的schedule...()方法之一。任何需要在主 (ui) 线程上执行的操作都可以包含在 runOnUiThread(() -> { ...}) 中。如果不再需要这些对象,请务必在 TimerTaskTimer 上调用 cancel()。取消Timer 也会取消TimerTask

    这可能是这样的:

    public class TimerTaskActivity extends Activity {
    
        Timer timer;
        TimerTask timerTask;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.timertask);
            ...
        }
    
        @Override
        protected void onStart() {
            super.onStart();
            timer = new Timer();
            timerTask = new TimerTask() {
    
                @Override
                public void run() {
                    runOnUiThread(() -> {
                        ....
                    });
                }
            };
            timer.scheduleAtFixedRate(timerTask, 2000, 2000);
        }
    
        @Override
        protected void onPause() {
            super.onPause();
            timer.cancel();
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-30
      • 1970-01-01
      • 1970-01-01
      • 2016-09-29
      • 2023-04-03
      相关资源
      最近更新 更多