更新GUI:Runnables vs Messages

Mis*_*ith 46 user-interface android message runnable

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

  1. 将java.lang.Runnable与以下任何方法一起使用:

    Activity.runOnUiThread(Runnable)
    View.post(Runnable)
    View.postDelayed(Runnable, long)
    Handler.post(Runnable)
    
    Run Code Online (Sandbox Code Playgroud)
  2. 使用android.os.Message:

    Handler.sendMessage(Message) / Handler.handleMessage(Message)
    
    Run Code Online (Sandbox Code Playgroud)

您也可以使用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), ...
    
    Run Code Online (Sandbox Code Playgroud)
  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?
        }
    
    Run Code Online (Sandbox Code Playgroud)

恕我直言,消息不是要走的路,因为:

  • 对于新的非android程序员来说并不容易理解(在构造期间处理程序挂钩到它的线程).
  • 如果消息跨越进程边界,则对象有效负载应为Parcellable.
  • 消息被重用(如果没有正确清理,则容易出错?)
  • 处理程序具有双重角色(它发送消息,但也处理它们)
  • 消息属性是公共的,但也提供getter/setter.

另一方面,Runnables遵循众所周知的命令模式,并且更加程序员友好且可读.

那么使用Messages over Runnables有什么好处呢?在现代Android编程中,消息是否被推入后台?你有什么办法可以用Runnables无法完成的消息吗?

提前致谢.

Jay*_*yer 21

我会说使用Messagevs与a 之间没有什么区别Runnable.它主要归结为个人偏好.为什么?查看源代码,您会发现发布一个Runnable使用相同的确切消息传递机制.它只是附加Runnable到a 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;
}
Run Code Online (Sandbox Code Playgroud)

参考:Grep代码 - 处理程序


key*_*rdr 12

Messages可以重复使用,因此可以减少创建的对象数量,减少GC.您最终也会减少类和匿名类型.

一个很大的优点是发送Message给a 的类Handler不需要知道关于它的实现的任何信息Message.这有助于封装,具体取决于它的使用位置.

最后考虑清洁度之间的差异

mHandler.obtainMessage(DO_STUFF, foo).sendToTarget();
Run Code Online (Sandbox Code Playgroud)

VS

final Foo tempFoo = foo;
mHandler.post(new Runnable(){
    @Override
    public void run(){
        doStuff(tempFoo);
    }
};
Run Code Online (Sandbox Code Playgroud)

如果你有几个地方你需要doStuff(),前者更具可读性,你将减少代码重复.

  • Runnables也可以重复使用,它也是一个接口,您可以以比您显示的方式更清晰的方式实例化(也是我发布的那个:)). (3认同)

Can*_*ner 4

HandlerrunOnUiThread()根据文档,接口提供的功能比 多得多:

处理程序有两个主要用途:
(1) 安排消息和可运行对象在将来的某个时刻执行
(2) 将要在与您自己的线程不同的线程上执行的操作排队。

runOnUiThread仅执行 (2) 的子集。即“将要在UI 线程上执行的操作排入队列”

因此,IMO 除非您需要这些额外的功能,否则runOnUiThread这就是足够的且首选的方式。