处理程序、线程和视图操作

Handlers, Threads and View manipulation

我正在尝试从我的 Fragment 的 onResume() 方法中操作 TextView。我定义了一个处理程序,并在调用处理程序的 post() 后尝试从 run() 中更改文本。虽然这确实改变了 TextView 的文本,但我尝试在 Handler 外部操作相同的 TextView,但是 TextView 的文本没有改变。这种情况下发生了什么,为什么 TextView 没有更改为 "BAR"。我执行的所有代码都在下面:

@Override
public void onResume(){
    super.onResume();

    mHandler = new Handler();
    Looper looper = mHandler.getLooper();
    Thread thread = looper.getThread();
    Log.v("THREAD",thread.getName());
    // prints main in logcat

    mHandler.post(new Runnable(){

        @Override
        public void run() {
            try {

                // TextView's text changes to "FOO"
                mTextView.setText("FOO");
            }
            catch(Exception exception){

                exception.toString();
            }
        }
    });

    // Logcat prints this message  
    Log.v("AFTER HANDLER","AFTER HANDLER");
    // TextView's text does not change to "BAR"
    mTextView.setText("BAR");
}

如果我遗漏了一些基本的东西,我深表歉意,但对此的任何澄清都会非常有帮助。谢谢!

Handler.post(Runnable r) 导致 r 被添加到消息队列。它不会立即 运行。在您的情况下,首先设置 "BAR",然后设置 "FOO"。

更多详情here

Handler.post() 适用于您希望从 UI 线程外部执行 UI 操作的情况。当它添加你传递给方法的 运行nable 时,并将其排队,以便在下一次 UI 传递时,你的 运行nable 将 运行.

onResume() 无论如何都会在 UI 线程上调用,因此不需要在 UI 线程上排队此操作。它的工作方式不会改变 - 在下一个 UI 通道(不是当前通道,下一个 通道),TextView's 文本将改变到 "FOO".

在 onResume 方法中 UI 线程的当前传递中,您还将文本设置为 "BAR"。一瞬间,TextView 真的显示了这段文字。但是,在不久之后发生的下一个 UI 传递中,"BAR" 文本被替换为 "FOO"。

这就是您看不到 "FOO" 文本的原因。您正在安排另一个 UI 之后立即通过,并且在您甚至没有注意到它有所不同之前就替换了文本。

有可能mTextView.setText("BAR")是第一个,mTextView.setText("FOO")是第二个

下面的代码会怎样?

@Override
public void onResume(){
    super.onResume();

    mHandler = new Handler();
    Looper looper = mHandler.getLooper();
    Thread thread = looper.getThread();
    Log.v("THREAD",thread.getName());
    // prints main in logcat

    mHandler.post(new Runnable(){

        @Override
        public void run() {
            try {
                Log.v("Which is earlier?", "FOO");
                mTextView.setText("FOO");
            }
            catch(Exception exception){

                exception.toString();
            }
        }
    });

    Log.v("Which is earlier?", "BAR");
    mTextView.setText("BAR");
}