更新GUI:可运行对比消息
要从其他线程更新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? }
恕我直言,消息是不是要走的路,因为:
- 新的非android程序员不容易理解(处理程序在构build线程时挂钩)。
- 如果消息跨越进程边界,则对象有效内容应该是可包装的。
- 消息被重用(如果没有正确清理,容易出错)?
- 处理程序有双重angular色(它发送消息,但也处理它们)
- 消息属性是公共的,但也提供getter / setter。
另一方面,Runnables遵循着名的命令模式,并且程序员更友好,可读性更强。
那么使用消息优于Runnables? 在现代Android编程中,消息是否被推到了后台? 使用Runnables无法完成的消息有什么可做的吗?
提前致谢。
我会说使用一个Message
与一个Runnable
之间没有什么区别。 这主要归结为个人喜好。 为什么? 查看源代码,您会发现发布Runnable
使用相同的确切消息机制。 它只需将Runnable
附加到Message
并发送该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; }
Ref: Grep Code – 处理程序
Messages
可以被重用,所以创build的对象更less,GC更less。 您最终还会得到更less的类和匿名types。
一个很大的优点是发送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()
,前者更可读,你会有更less的代码重复。
根据文档, Handler
接口提供比runOnUiThread()
更多的function:
处理程序有两个主要用途:
(1)安排将来的消息和可运行的程序
(2)排队在不同于你自己的线程上执行的动作。
runOnUiThread
只做(2)的一个子集。 即“排队要在UI线程上执行的动作”
所以国际海事组织,除非你需要那些额外的functionrunOnUiThread
是足够和首选的方式。
我更喜欢Runnable
到Message
。 我认为使用Runnable
代码比Message
更清晰,因为事件处理代码非常接近事件。 另外,您可以避免定义常量和开关情况的开销。
我不认为使用Runnable
违反封装。 您可以将Runnable.run()
的代码提取到外部类中的另一个方法中,例如on...Event()
,或者甚至将其包装到EventHandler
对象中。 这两种方法比使用Message
更清晰,特别是当你需要在Message
存储引用时,因为使用Runnable
可以避免向下msg.obj
。 msg.obj
段msg.obj
也容易出错,有时效率不高。
而Runnable
也可以通过将其作为字段存储来重用。