安卓TextView.setText()调用和放大器;前Thread.sleep()方法返回块,直到睡眠()返回。为什么?放大器、睡眠、方法、TextView

2023-09-07 01:44:54 作者:深拥你@

在Android框架,如果 的TextView 的setText() 方法被调用,它返回的 Thead.sleep() 叫的,那么屏幕该设备不会显示给定的文本后才睡眠()返回。为什么呢?

In the Android framework, if a TextView's setText() method is called, and after it returns Thead.sleep() is called, then the screen of the device does not display the given text until after sleep() has returned. Why?

public class SleeperActivity extends Activity {
    public void onCreate(Bundle bundle) {
        super.onCreate(bundle);
        setContentView(R.layout.main);
    }

    public void doDelay(View view) {
        try {
            TextView textView = (TextView) view;
            textView.setText("Sleeping");
            Log.d("Sleeper", "This log entry is invoked before sleeping");
            Thread.sleep(5000L);
            textView.setText("Ready");
        } catch (InterruptedException e) { finish(); }
    }
}

布局,未显示,有他的的onClick 属性设置为 doDelay按钮()

在上面的code编译并运行,单击该按钮,在的setText的第一次调用()通过文本不会出现在屏幕上,直到线程之后睡了五秒钟,即使日志条目显示在日志中的5秒开始经过前。

When the above code is compiled and run, and the button is clicked, the text passed in the first invocation of setText() does not appear on the screen until after the thread has slept for five seconds, even though the log entry appears in the log before those five seconds begin to elapse.

为什么会出现这种情况,什么应该我做这件事作出的setText在第一次调用中传递文本()出现在屏幕上的线程开始之前睡觉?

Why does this happen, and what ought I to do about it to make the text passed in the first call to setText() appear on the screen before the thread begins to sleep?

推荐答案

原因所观察到的行为是查看是完成每一个周期,通过后才能重绘事件循环。 Android的的onCreate()的方法,以及触摸事件,如点击一个按钮,通过该框架从事件循环中调用。因此,方法,如的onCreate()的onClick()将在任何完成执行查看是重画,会有在显示屏上没有明显的效果这些方法已经返回之后。更改查看■从内这些方法做将只能从该事件循环周期完成后成为可见调用的框架表示方法(的onCreate( )的onClick(),等的)。

The reason for the observed behavior is that Views are only redrawn after the completion of each cycle through the event loop. The android onCreate() method, as well as touch events such as clicking a button, are invoked by the framework from within the event loop. Thus, methods such as onCreate() or onClick() will execute to completion before any Views are redrawn, and there will be no visible effect on the display until after those methods have returned. Changes to Views made from within those methods will only become visible after completion of the event loop cycle from within which the framework invoked said method (onCreate(), onClick(), etc.).

要实现的问题所要求的行为,的调用睡眠()方法必须发生的 的完成事件循环周期后,在其中你调用的setText()你想在时间线程阻塞要显示的文字。这样做的一个方法就是通过调用替换)调用睡眠( View.post() View.post()需要的Runnable 的run()方法将被调用的在的事件循环当前周期已经完成,该框架显示您希望在线程被阻塞的时候,看到的文字。通过将呼叫视频下载()在的Runnable 的的run()的方法是这样的:

To achieve the behavior requested in the question, invocation of the sleep() method must occur after completion of the event loop cycle in which you invoked setText() with the text you want to be displayed during time the thread is blocking. One way to do this is simply to replace the call to sleep() with a call to View.post(). View.post() takes a Runnable whose run() method will be called after the current cycle of the event loop has completed and the framework has displayed the text you want to see during the time the thread is blocking. Change the doDelay() method in the question by placing the call to Thread.sleep() inside a Runnable's run() method like this:

    public void doDelay(View view) {
        final TextView textView = (TextView) view;
        textView.setText("Sleeping");
        textView.post(new Runnable() {
            public void run() {
                try {
                    Log.d("Sleeper", "Thread " + Thread.currentThread() + " going to sleep...");
                    Thread.sleep(5000L);
                    Log.d("Sleeper", "Thread " + Thread.currentThread() + " now awake");
                    textView.setText("Ready");
                } catch (InterruptedException e) { finish(); }
            }
        });
    }

我要感谢去到加布Sechan ,他的指导让我脱胶足以回答我的问题。

My thanks goes to to Gabe Sechan, whose guidance got me unstuck enough to answer my own question.