更新GUI:可运行对比消息

要从其他线程更新GUI,基本上有两种主要方法:

  1. 使用java.lang.Runnable与这些方法中的任何一个:

    Activity.runOnUiThread(Runnable) View.post(Runnable) View.postDelayed(Runnable, long) Handler.post(Runnable) 
  2. 使用android.os.Message:

     Handler.sendMessage(Message) / Handler.handleMessage(Message) 

你也可以使用AsyncTask,但是我的问题更关注于更新一个非常简单的组件的用例。 让我们看看如何使用这两种方法来完成:

  1. 使用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), ... 
  2. 使用消息:

     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。

一个很大的优点是发送MessageHandler的类不需要知道任何有关该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是足够和首选的方式。

我更喜欢RunnableMessage 。 我认为使用Runnable代码比Message更清晰,因为事件处理代码非常接近事件。 另外,您可以避免定义常量和开关情况的开销。

我不认为使用Runnable违反封装。 您可以将Runnable.run()的代码提取到外部类中的另一个方法中,例如on...Event() ,或者甚至将其包装到EventHandler对象中。 这两种方法比使用Message更清晰,特别是当你需要在Message存储引用时,因为使用Runnable可以避免向下msg.objmsg.objmsg.obj也容易出错,有时效率不高。

Runnable也可以通过将其作为字段存储来重用。