【问题标题】:Updating UI using a Handler freezes my app使用处理程序更新 UI 会冻结我的应用程序
【发布时间】:2013-03-10 01:03:50
【问题描述】:

我正在尝试制作时钟,使用 TextView :)

这里有人告诉我,我不能使用普通线程来更改 UI,而是 HandlerAsyncTask。几天前我设法让它工作,但不是一个一致的线程。

现在我想要的是一个始终如一的线程,它总是在更改我的Textview 的文本。我试过用这个,但没有用,有什么帮助吗?

private void startClock() {
    new Handler().postDelayed(new Runnable(){

        @Override
        public void run() {
            while (true) {
                final long millis = System.currentTimeMillis() - MainActivity.startedAt;
                clock.setText("" + millis);
                runOnUiThread (new Runnable() {

                    @Override
                    public void run() {
                        clock.setText("" + millis);
                    }
                });

                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }, 2000);
}

【问题讨论】:

  • 为什么不使用Timer 类呢?会让你的生活更简单。见这里:stackoverflow.com/questions/15317600/…
  • 这可能是一个解决方案,不知道 Timer 类,但这只是一次运行,对吧?我想要一个时钟一直在运行..我需要多次调用计时器,并且可能导致我同样的冻结..感谢您的回复!真的很感激;)总是有人在这里帮助:)
  • 不,您可以安排定期重复运行,它会为您处理大部分逻辑。
  • 怎么样?只是多次调用它?像在一个循环内?但我不能使用 while(true),接受答案的另一个人告诉我:/
  • 您基本上只需将Timer 传递给一个名为TimerTask 的回调函数,并给它一个固定的时间间隔来执行TimerTask。不需要循环。请参阅我链接的问题以获取更多详细信息...

标签: android android-ui android-handler


【解决方案1】:

你应该摆脱:

while(true) {
    ....
    sleep(1000);
    ...
}

因为这会让你的线程永远卡住。你的程序应该是这样工作的:

private Handler mHandler = new Handler();

@Override
public void onResume() {
    super.onResume();
    mHandler.removeCallbacks(mUpdateClockTask);
    mHandler.postDelayed(mUpdateCLockTask, 100);
}

@Override
public void onPause() {
    super.onPause();
    mHandler.removeCallbacks(mUpdateClockTask);
}

private Runnable mUpdateClockTask = new Runnable() {
    public void run() {
        updateClock();
        mHandler.postDelayed(mUpdateClockTask, 2000);
    }
};

updateClock() 中,您可以进行所有的 UI 更新。

【讨论】:

  • 我不知道 while true 会导致任何问题...我会将 while(true) 更改为 while(toContinue()).. 并检查活动是否仍然在使用中..当我改变活动时, toContinue() 会返回 false.. 不知道一段时间(true)会滞后这个,但有道理.. 因为有像 onResume 和 onPause 这样的方法.. 每次我改变活动,但它很奇怪......因为我什至没有改变活动,然后它就冻结了......
  • 非常感谢 lenik,你解决了我的问题,但如果可能的话,我想理解它:)
  • android 编程的第一条规则——永远不要使用while(true),除非里面有明确的出口,很快就会触发。您的所有功能都必须完成工作并尽快返回。如果有些东西没有准备好——留下它,下次你来同一个地方时再检查一次。使用来自系统和/或计时器的回调而不是等待。如果您还有什么要我解释的,请提出问题,这是一个非常广泛的话题,适合 500 字节的评论 =)
  • 非常欢迎像你这样的 lenik 人,非常感谢。你不需要说两次,我是android编程的新手,还在学习,只有几天。但我不会忘记,“不要花时间在方法上”,“使用回调和计时器”。它对我来说足够的信息 :) 再次感谢你 ;)
【解决方案2】:

在这里查看示例https://stackoverflow.com/a/11140429/808940

另请注意,您的代码中有重复的行:

clock.setText(""+millis);

它同时出现在runOnUiThread和主处理程序中,它应该只出现在runOnUiThread runnable中

【讨论】:

  • @DarkLink 得到这样的答案后请不要更改原始代码。我还原了你的代码。
猜你喜欢
  • 1970-01-01
  • 2013-08-02
  • 2017-10-03
  • 2017-03-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多