处理程序、线程和视图操作
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");
}
我正在尝试从我的 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");
}