当android应用程序运行时,一个主线程被创建(也称作UI线程),此线程主要负责处理UI相关的事件,由于Android采用UI单线程模型,所以只能在主线程中对UI元素进行操作,如果在非UI线程直接对UI进行了操作,则会报错,另外,对于运算量较大的操作和IO操作,我们需要新开线程来处理这些工作,以免阻塞UI线程,子线程与主线程之间是怎样进行通信的呢?此时就要采用消息循环机制(Looper)与Handler进行处理。
一、基本概念
ThreadLocal保证了每个线程都有自己的Looper对象。在android中主线程启动会创建属于自己的looper对象,这时候如果我们在去调用prepare就会抛Only
one Looper may be created per thread;但子线程并不会自己创建looper对象,需要我们手动调用prepare创建属于该线程的looper对象。
Looper:每一个线程都可以产生一个Looper,用来管理线程的Message,Looper对象会建立一个MessgaeQueue数据结构来存放message。
Handler:与Looper沟通的对象,可以push消息或者runnable对象到MessgaeQueue,也可以从MessageQueue得到消息。
查看其构造函数:
Handler()
Default constructor associates this handler with the queue forthe current thread.//如不指定Looper参数则默认利用当前线程的Looper创建
Handler(Looper looper)
Use the provided queue instead of the default one.//使用指定的Looper对象创建Handler
线程A的Handler对象引用可以传递给别的线程,让别的线程B或C等能送消息来给线程A。
线程A的Message Queue里的消息,只有线程A所属的对象可以处理。
注意:Android里没有global的MessageQueue,不同进程(或APK之间)不能通过MessageQueue交换消息。
二、Handler通过Message通信的基本方式
使用Looper.myLooper可以取得当前线程的Looper对象。
使用mHandler = new Handler(Looper.myLooper()); 可产生用来处理当前线程的Handler对象。
使用mHandler = new Handler(Looper.getMainLooper()); 可诞生用来处理main线程的Handler对象。
使用Handler传递消息对象时将消息封装到一个Message对象中,Message对象中主要字段如下:
public int arg1 当需要传递的消息是整形时arg1 和 arg2 是一种低成本的可选方案,他使用 setData()/getData()访问或修改字段。
public int arg2 同上
public Object obj 可传送的任意object类型.
public int what Int类型用户自定义的消息类型码
Message对象可以通过Message类的构造函数获得,但Google推荐使用Message.obtain()方法获得,该方法会从全局的对象池里返回一个可复用的Messgae实例,API中解释如下:
Message()
Constructor (but the preferred way to get a Message is to callMessage.obtain()).
Handler发出消息时,既可以指定消息被接受后马上处理,也可以指定经过一定时间间隔之后被处理,如sendMessageDelayed(Message msg, long delayMillis),具体请参考API。
Handler消息被发送出去之后,将由handleMessage(Message msg)方法处理。
注意:在Android里,新诞生一个线程,并不会自动建立其Message Loop
可以通过调用Looper.prepare()为该线程建立一个MessageQueue,再调用Looper.loop()进行消息循环。
本文深入解析Android中的消息机制,包括Looper、Handler与MessageQueue的工作原理及其交互方式。介绍了如何在主线程与子线程间通过Handler传递消息,实现UI更新与后台任务处理的有效分离。
1991

被折叠的 条评论
为什么被折叠?



