Android:Looper类,Looper.prepare()和Looper.loop()

工作线程:在android应用程序中,我们创建的Activity、Service、Broadcast等都是在主线程(UI线程)处理的,但一些比较耗时的操作,如I/O读写的大文件读写,数据库操作以及网络下载需要很长时间,为了不阻塞用户界面,出现ANR的响应提示窗口,这个时候我们可以考虑创建一个工作线程(继承Thread类或者实现Runnable接口)来解决。

使用工作线程容易出现的问题:对于Android平台来说UI控件都没有设计成为线程安全类型,所以需要引入一些同步的机制来使其刷新,否则使用工作线程更新UI会出现异常。


Looper:

针对以上问题,android采用消息循环机制来处理线程间的通信,Android消息循环是针对线程的(每个线程都可以有自己的消息队列和消息循环),Android系统中Looper负责管理线程的消息队列和消息循环, 可以通过Loop.myLooper()得到当前线程的Looper对象,通过Loop.getMainLooper()可以获得当前进程的主线程的Looper对象。Looper对象是什么呢?其实Android中每一个Thread都对应一个Looper,Looper可以帮助Thread维护一个消息队列,负责在多线程之间传递消息的一个循环器。一个线程可以存在(当然也可以不存在)一个消息队列和一个消息循环(Looper),但是创建的工作线程默认是没有消息循环和消息队列的,如果想让该线程具有消息队列和消息循环,需要在线程中首先调用Looper.prepare()来创建消息队列,然后调用Looper.loop()进入消息循环。


Android官方文档中Looper的介绍:

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.

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();
      }
  }

Android中的Looper类,是用来封装消息循环和消息队列的一个类,用于在android线程中进行消息处理。handler其实可以看做是一个工具类,用来向消息队列中插入消息的。 

(1) Looper类用来为一个线程开启一个消息循环。 

 默认情况下android中新诞生的线程是没有开启消息循环的。(主线程除外,主线程系统会自动为其创建Looper对象,开启消息循环。) 

Looper对象通过MessageQueue来存放消息和事件。一个线程只能有一个Looper,对应一个MessageQueue。 

(2) 通常是通过Handler对象来与Looper进行交互的。Handler可看做是Looper的一个接口,用来向指定的Looper发送消息及定义处理方法。 
默认情况下Handler会与其被定义时所在线程的Looper绑定,比如,Handler在主线程中定义,那么它是与主线程的Looper绑定。 
mainHandler = new Handler() 等价于new Handler(Looper.myLooper()). 
Looper.myLooper():获取当前进程的looper对象,类似的 Looper.getMainLooper() 用于获取主线程的Looper对象。 

(3) 在非主线程中直接new Handler() 会报如下的错误: 
E/AndroidRuntime( 6173): Uncaught handler: thread Thread-8 exiting due to uncaught exception 
E/AndroidRuntime( 6173): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare() 
原因是非主线程中默认没有创建Looper对象,需要先调用Looper.prepare()启用Looper。 

(4) Looper.loop(); loop函数从MessageQueue中从前往后取出Message,然后通过HandlerdispatchMessage函数进行消息的处理(可见消息的处理是Handler负责的),消息处理完了以后通过Message对象的recycle函数放到Message Pool中,以便下次使用,通过Pool的处理提供了一定的内存管理从而加速消息对象的获取。 

注意:Looper.loop()中是个while循环,只有对它所在线程的Looper调用了quit()函数,Looper.loop()函数才能完成,其后的代码才能得以运行。一个线程对应一个Looper,一个Looper对应一个消息队列MessageQueue。

  • 7
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: Looper.prepare()和Looper.loop()是Android中消息循环机制的核心方法。Looper.prepare()用于创建当前线程的消息循环对象,而Looper.loop()则用于启动消息循环,使得消息队列中的消息得以被处理。在Android中,UI线程就是一个消息循环线程,通过Looper.prepare()和Looper.loop()的配合,可以实现UI线程的消息循环机制,从而保证UI界面的流畅性和响应性。具体来说,Looper.prepare()会创建一个Looper对象,并将其存储在ThreadLocal中,而Looper.loop()则会不断地从消息队列中取出消息,并将其分发到对应的Handler中进行处理。在消息处理完成后,Looper.loop()会继续等待下一个消息的到来,从而实现消息循环的效果。 ### 回答2: 在Java中,Looper.prepare()和Looper.loop()是与Android消息循环机制相关的两个方法。 首先,Looper.prepare()方法是用来创建当前线程的消息队列Looper对象。每个线程只能有一个Looper对象,用于处理该线程接收到的消息。在调用Looper.prepare()方法后,会创建一个Looper对象,并将其保存在ThreadLocal中,以便该线程其他地方可以直接访问。一般来说,在创建Handler之前,需要先调用Looper.prepare()方法。 其次,Looper.loop()方法是调用当前线程的消息循环机制。一旦调用该方法,程序就会进入一个无限循环的状态,不断地从消息队列中取出消息并处理。在处理完一条消息后,继续取出下一条消息进行处理,以此推。这个无限循环直到Looper对象调用了quit()方法,才会退出循环。 在Android开发中,通常在主线程中会调用Looper.prepare()和Looper.loop()方法来初始化和启动消息循环,以便接收并处理用户交互事件或其他异步事件。然后通过创建Handler对象,将需要处理的消息发送到消息队列中,Looper.loop()方法会负责从消息队列中轮询消息,并根据消息型调用相应的Handler处理函数。 总之,Looper.prepare()方法创建当前线程的消息队列,Looper.loop()方法负责启动消息循环并处理队列中的消息,这两个方法共同构成了Java中利用消息队列实现消息循环机制的基础。 ### 回答3: 在Java中,Looper.prepare()和Looper.loop()是Android系统中的主要组件之一——消息循环机制(Message Loop Mechanism)中的关键方法。消息循环机制是Android系统用来实现多线程之间通信的重要工具。 首先,Looper.prepare()的作用是在当前线程中创建一个消息队列(Message Queue)和Looper对象。消息队列用于存储待处理的消息,而Looper对象则用于管理消息队列。每个线程最多只能有一个Looper对象,保证线程与消息队列一一对应。 其次,Looper.loop()的作用是启动消息循环,开始不断地从消息队列中取出消息并依次处理。该方法会一直循环执行,直到调用Looper.quit()方法停止消息循环。 具体来说,当调用Looper.prepare()方法时,会为当前线程创建一个消息队列,并通过ThreadLocal保存Looper对象。然后通过Looper.myLooper()方法可以获取当前线程的Looper对象。接下来,通过Looper.loop()方法启动消息循环,从消息队列中获取消息,并传递给Handler进行处理。当消息队列为空时,Looper.loop()方法会进入休眠状态,等待新的消息进入队列。在消息循环期间,调用Looper.quit()方法可以停止消息循环,并释放相关资源。 通过消息循环机制,可以实现多线程间的异步通信。主线程通常会创建一个消息循环,用于处理UI事件和与用户交互的消息。在子线程中,通过调用Looper.prepare()和Looper.loop()方法,可以为当前线程创建独立的消息队列,从而实现线程间的消息传递和任务调度。 总之,Looper.prepare()和Looper.loop()是Java中实现消息循环机制的关键方法,前者用于创建消息队列和Looper对象,后者用于启动消息循环并处理消息。通过合理地使用消息循环机制,可以实现多线程之间的高效通信和任务调度。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值