3

我正在编写一个 android 应用程序,它需要在千分之几秒内显示一些文本,然后再次将其空白。我现在拥有的是显示文本,然后使用 Thread.sleep,然后将文本设置回 null。相反,当我按下按钮时,应用程序会挂起一段时间,文本永远不会出现,并且 logcat 会显示“跳过了 xxx 帧!应用程序可能在其主线程上做的工作过多。” 发生了什么事,有没有更好的做事方式?

4

2 回答 2

4

尝试使用可运行的。

private Handler mHandler = new Handler();

//code to make text appear...

    mHandler.postDelayed(makeTextDisapear , 3000); // Replace 3000 with the number of milliseconds you want the text to display.

    private Runnable makeTextDisapear = new Runnable() {
            public void run() {
                // code to make text dissapear

                }
            };
于 2012-10-22T02:03:28.967 回答
2

虽然其他答案有助于解决您的问题,但您的问题也是为什么会发生这种情况:

调用任一静Thread.sleep()态方法会使调用该方法的线程进入暂停状态(大致)您指定的时间量(不能保证与指定时间完全匹配)。

在 Android 中,必须在“主”ui 线程上执行 Ui 操作,因为 Ui 框架并非设计为线程安全的。也就是说,当您设置 a 的文本时,您必须在主线程上 TextView调用。将向主要发布一条消息以重新布局并使 TextView(和父母)无效。在不久的将来,这些消息将被处理并更新视图层次结构。textView.setText(...)setTextLooper

setText不直接做这个工作,因为这个工作量很大,直接做不会让框架批量处理这样的请求。

如果您随后调用Thread.sleep(...),则您将主 ui 线程置于暂停状态,但是,该线程通常会执行 TextView 和父级的重新布局和失效。

Android 希望能够在 16 毫秒内渲染一个新帧(如果有任何变化)以保持大于 60 fps。如果您的主线程正在做一些密集的事情,或者被暂停(通过睡眠)任何会威胁到 16 毫秒的重要时间,那么您看到的错误消息将发布到 logcat。

虽然在 Lollipop 中实际渲染是在它自己的渲染线程上执行的,但它仍然需要从主线程及时更新。

至于如何解决这个问题,请参阅 Jason 的回答,或者使用

textView.setText("show me!");    
textView.postDelayed(new Runnable() { 
     public void run() { 
         textView.setText(""); 
     }
}, 30);

如果这种情况经常发生,请Runnable通过将其保留为字段来避免分配每次。

请注意,在任何一种情况下,创建匿名内部类 (the Runnable) 都有可能导致 Activity 内存泄漏,但这是另一回事。

于 2015-05-01T08:23:20.547 回答