要从其他线程更新GUI,基本上有两种主要方法:
将java.lang.Runnable与以下任何方法一起使用:
Activity.runOnUiThread(Runnable)
View.post(Runnable)
View.postDelayed(Runnable, long)
Handler.post(Runnable)
使用android.os.Message:
Handler.sendMessage(Message) / Handler.handleMessage(Message)
您也可以使用AsyncTask,但我的问题更侧重于更新非常简单的组件的用例。让我们看看如何使用这两种方法完成:
使用Runnables:
TextViev tv = ...;
final String data = "hello";
Runnable r = new Runnable() {
@Override
public void run(){
tv.setText(data);
}
};
//Now call Activity.runOnUiThread(r) or handler.post(r), ...
使用消息:
Message m = handler.obtainMessage(UPDATE_TEXT_VIEW, "hello");
handler.sendMessage(m);
//Now on handler implementation:
@Override
public void handleMessage(Message msg) {
if(msg.what == UPDATE_TEXT_VIEW){
String s = (String) msg.obj;
tv.setText(data);
} ... //other IFs?
}
恕我直言,消息不是要走的路,因为:
另一方面,Runnables遵循众所周知的命令模式,对程序员更友好,更易读。
那么使用Messages over Runnables有什么好处?在现代Android编程中,消息是否被推入后台?有什么可以用Runnables无法完成的消息吗?
提前致谢。
答案 0 :(得分:20)
我想说使用Message
与Runnable
之间没有什么区别。它主要归结为个人偏好。为什么?查看源代码,您会发现发布Runnable
使用相同的确切消息传递机制。它只是将Runnable
附加到Message
并发送。
4.4.2源代码
public final boolean post(Runnable r) {
return sendMessageDelayed(getPostMessage(r), 0);
}
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
答案 1 :(得分:12)
Messages
可以重复使用,因此可以减少创建的对象数量,减少GC的使用量。您最终也会减少类和匿名类型。
一个很大的优势是,向Message
发送Handler
的班级不需要了解Message
的实施情况。这有助于封装,具体取决于它的使用位置。
最后考虑
之间的清洁差异mHandler.obtainMessage(DO_STUFF, foo).sendToTarget();
VS
final Foo tempFoo = foo;
mHandler.post(new Runnable(){
@Override
public void run(){
doStuff(tempFoo);
}
};
如果你有几个地方需要doStuff()
,前者的可读性更高,你的代码重复次数也会减少。
答案 2 :(得分:4)
Handler
界面提供了比runOnUiThread()
更多的功能
Handler有两个主要用途:
(1)安排消息和runnables作为将来的某个点执行 (2)将要在不同于自己的线程上执行的动作排入队列。
runOnUiThread
只做(2)的子集。 ie"将要执行的操作排入 UI线程 "
所以IMO除非你需要那些额外的功能runOnUiThread
是充分和首选的方式。
答案 3 :(得分:2)
我更喜欢Runnable
到Message
。我认为使用Runnable
的代码比Message
更清晰,因为事件处理代码非常接近事件。此外,您可以避免定义常量和切换案例的开销。
我不认为使用Runnable
会违反封装。您可以将Runnable.run()
中的代码提取到外部类中的另一个方法中,例如on...Event()
,或者甚至将其包装到EventHandler
对象中。两种方式都比使用Message
更清晰,尤其是当您需要Message
中的商店引用时,因为使用Runnable
可以避免向下转换msg.obj
。无名字段msg.obj
也容易出错,有时也无法理解。
Runnable
也可以通过将其存储为字段来重复使用。