我正在编写一个 android 应用程序,它需要在千分之几秒内显示一些文本,然后再次将其空白。我现在拥有的是显示文本,然后使用 Thread.sleep,然后将文本设置回 null。相反,当我按下按钮时,应用程序会挂起一段时间,文本永远不会出现,并且 logcat 会显示“跳过了 xxx 帧!应用程序可能在其主线程上做的工作过多。” 发生了什么事,有没有更好的做事方式?
2 回答
尝试使用可运行的。
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
}
};
虽然其他答案有助于解决您的问题,但您的问题也是为什么会发生这种情况:
调用任一静Thread.sleep()
态方法会使调用该方法的线程进入暂停状态(大致)您指定的时间量(不能保证与指定时间完全匹配)。
在 Android 中,必须在“主”ui 线程上执行 Ui 操作,因为 Ui 框架并非设计为线程安全的。也就是说,当您设置 a 的文本时,您必须在主线程上
TextView
调用。将向主要发布一条消息以重新布局并使 TextView(和父母)无效。在不久的将来,这些消息将被处理并更新视图层次结构。textView.setText(...)
setText
Looper
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 内存泄漏,但这是另一回事。