Android 中的 Looper 对象

Android 官网对Looper对象的说明:

public class Looper
   
   
    
    extends Object
   
   
 

Class used to run a message loop for a thread. Threads by default do not have a message loop associated with them; to create one, call prepare() in the thread that is to run the loop, and then loop() to have it process messages until the loop is stopped.

Most interaction with a message loop is through the Handler class.

    在消息处理机制中,消息都是存放在一个消息队列中去,而应用程序的主线程就是围绕这个消息队列进入一个无限循环的,直到应用程序退出。如果队列中有消息,应用程序的主线程就会把它取出来,并分发给相应的Handler进行处理;如果队列中没有消息,应用程序的主线程就会进入空闲等待状态,等待下一个消息的到来。在Android应用程序中,这个消息循环过程是由Looper类来实现的,它定义在frameworks/base/core/java/android/os/Looper.java文件中。

    先理解几个概念:

Message:消息,其中包含了消息ID,消息处理对象以及处理的数据等,由MessageQueue统一列队,终由Handler处理。

Handler:处理者,负责Message的发送及处理。使用Handler时,需要实现handleMessage(Message msg)方法来对特定的Message进行处理,例如更新UI等。

MessageQueue:消息队列,用来存放Handler发送过来的消息,并按照FIFO规则执行。当然,存放Message并非实际意义的保存,而是将Message以链表的方式串联起来的,等待Looper的抽取。

Looper:消息泵,不断地从MessageQueue中抽取Message执行。因此,一个MessageQueue需要一个Looper

Thread:线程,负责调度整个消息循环,即消息循环的执行场所。

  

        参考:Android Looper和Handler

This is a typical example of the implementation of a Looper thread, using the separation of prepare() and loop() to create an initial Handler to communicate with the Looper.

  class LooperThread extends Thread {
      public Handler mHandler;
      
      public void run() {
          Looper.prepare();
          
          mHandler = new Handler() {
              public void handleMessage(Message msg) {
                  // process incoming messages here
              }
          };
          
          Looper.loop();
      }
  }

在run()方法中做了两件事情,一是创建了一个Handler实例,二是通过Looper类使该线程进入消息循环中。

主要方法简介:

static void  loop() :  Run the message queue in this thread.

static void prepare() :  Initialize the current thread as a looper.若不调用,则异常:Can‘t create handler inside thread that has not called Looper.prepare()。

Handler处理消息总是在创建Handler的线程里运行。而我们的消息处理中,不乏更新UI的操作,不正确的线程直接更新UI将引发异常。因此,需要时刻关心Handler在哪个线程里创建的。

如何更新UI才能不出异常呢?SDK告诉我们,有以下4种方式可以从其它线程访问UI线程:

·      Activity.runOnUiThread(Runnable)

·      View.post(Runnable)

·      View.postDelayed(Runnable, long)

·      Handler

其中重点说一下的是View.post(Runnable)方法。在post(Runnable action)方法里View获得当前线程UI线程Handler然后将action对象postHandler里。在Handler里,它将传递过来的action对象包装成一个MessageMessagecallbackaction),然后将其投入UI线程的消息循环中。在Handler再次处理该Message时,有一条分支(未解释的那条)就是为它所设,直接调用runnablerun方法。而此时,已经路由到UI线程里,因此,我们可以毫无顾虑的来更新UI

几点小结:

·      Handler的处理过程运行在创建Handler的线程里

·      一个Looper对应一个MessageQueue

·      一个线程对应一个Looper

·      一个Looper可以对应多个Handler

·      不确定当前线程时,更新UI时尽量调用post方法

1.主线程:

Handler mainThreadHandler = new Handler(Looper.getMainLooper());

mainThreadHandler.post(runnable);

2.非主线程:

HandlerThread thread = new HandlerThread("Default Thread", Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
Handler defThreadHandler = new Handler(thread.getLooper());

defThreadHandler.post(runnable);

defThreadHandler.removeCallbacks(runnable);//Remove any pending posts of Runnable r that are in the message queue. 

3.线程池:

ExecutorService cachedThreadPool = Executors.newCachedThreadPool();

cachedThreadPool.execute(runnable);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

itzyjr

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值