调用 Handler 时是不是需要调用 Looper.prepare()

Posted

技术标签:

【中文标题】调用 Handler 时是不是需要调用 Looper.prepare()【英文标题】:Do we need invoking Looper.prepare() when invoking Handler调用 Handler 时是否需要调用 Looper.prepare() 【发布时间】:2016-11-09 05:45:59 【问题描述】:

我需要了解 Looper。 Looper 将咨询适当的 handler 来发送和处理与线程的 MessageQueue 关联的 Message 和 Runnable 对象。

默认情况下,线程没有与之关联的消息循环,因此也没有 Looper。要为某个线程创建 Looper 并专用于该线程以串行方式处理来自消息循环的消息,您可以使用 Looper 类。

以下是我没有显式调用 Looper 的代码

Thread background2 = new Thread(new Runnable() 

            @Override
            public void run() 

            for ( int i = 0; i < 5; i++) 
               final int v =i;
                    try    Thread.sleep(1000);
                  handler.post(new Runnable() 
                     @Override
                     public void run() 
                        txt.setText(txt.getText() +  "Thread 2 current i : " + String.valueOf(v) +System.getProperty("line.separator"));
                     
                  );
                     catch (Exception e) 
                        Log.v("Error", e.toString());
                    
                

            
        );

是不是表示task/runnable没有放入队列?上面的代码和这个有什么区别

Thread background3 = new Thread(new Runnable() 

            @Override
            public void run() 
     Looper.prepare();
            for ( int i = 0; i < 5; i++) 
               final int v =i;
                    try    Thread.sleep(1000);
                  handler.post(new Runnable() 
                     @Override
                     public void run() 
                        txt.setText(txt.getText()+ "Thread 3 set : " + String.valueOf(v) +System.getProperty("line.separator"));
                     
                  );
                     catch (Exception e) 
                        Log.v("Error", e.toString());
                    
                
Looper.loop();
            
        );

他们都访问一个相同的处理程序。它们都工作正常。

【问题讨论】:

一个Thread 不需要Looper 来发布到另一个ThreadHandler,如果这就是你要问的。您的示例中的 Handlers 用于其他 Threads,无论您在哪个 Threads 上创建它们。 你好,我现在很困惑,所以我的第二个例子有什么区别,我明确地调用 Looper.prepare(),但没有它,它仍然有效 Thread 创建一个Looper 意味着其他 Threads 可以向其发帖。您示例中的 Looper 并没有真正做任何事情,因为您没有向在那里创建的 Handler 发布任何内容,这就是您看不到差异的原因。 迈克,that other Threads can post to it 在这种情况下是什么?你能把它作为答案吗, 嗯,这里有很多答案已经涵盖了这一点,所以我宁愿找到一个重复的答案而不是发布一个重复的答案。无论如何,在您的第二个示例中,由于您在那个Thread 中开始一个Looper,您可以为那个Looper 创建一个Handler,将它传递给另一个Thread,然后传递给另一个Thread可以发布到它。您的示例Threads 将Runnables 发布到为Handlers 创建的任何其他Thread。他们不会将它们发布给自己。 【参考方案1】:

Thread 创建Looper 意味着您正在设置该Thread 以接收来自其他Threads 的消息。您的两个示例的行为完全相同,因为在第二个示例中您没有向Thread 发送任何内容。也就是说,background3Looper 并没有真正被使用。

在这两个示例中,您将Runnable 发布到为主要ThreadLooper 创建的Handler。您不是为 background2 等创建 Handler。那个Handler 属于主Thread 和它的Looper,你发布到它的任何东西都将被放入主队列,并在主Thread 上运行。

您的示例中唯一的区别是第二个Thread 有一个Looper,如果您愿意,您可以 发布到它。为此,您将创建另一个属于background3LooperHandler,然后发布到该Handler。不过,您并没有这样做,所以第二个 Thread 只是继续运行,不做任何其他事情。

Thread 不需要Looper 来简单地发布到另一个Thread 的处理程序,这就是您的示例所做的一切。另一个Thread——在这种情况下是主要的Thread——已经准备好并开始了它的Looper。您只是向它发送Runnables,您不需要自己的Looper 来执行此操作。

【讨论】:

如果我没有充分解释任何事情,请让我知道。 非常感谢 Mike 我知道了。您在评论中发布的其他帖子解释说 Looper 作为一种经理线程过于笼统。但你的回答很清楚。

以上是关于调用 Handler 时是不是需要调用 Looper.prepare()的主要内容,如果未能解决你的问题,请参考以下文章

tornado handler 服务调用

请教大家,在service中调用activity中handler对象?

Day475.GoogleProtobuf&Netty编解码器和handler 的调用机制 -netty

Day475.GoogleProtobuf&Netty编解码器和handler 的调用机制 -netty

Android源码学习 Handler之Looper

更新UI——Handler&runOnUiThread