Android消息机制 java常用类
来源:互联网 发布:网络星光大道张卫 编辑:程序博客网 时间:2024/06/09 21:48
消息驱动是一种进程或线程的运行模式。内部、外部的各种事件可以放到消息队列中按序处理。比如:Android的应用UI线程。
在windows的消息处理模型中,只有一个系统消息队列,这个队列是整个进程的核心,几乎所有动作都要转换成消息,放到这个队列中,消息处理在主线程完成。
也就是有多个线程发送消息,只有一个属于进程的消息队列,以及只有一个主线程处理消息队列中的消息。
Android的消息处理不一样。Android没有全局的消息队列,消息队列是和某个线程相关的。每个线程最多只有一个消息队列,消息的取出和处理也在线程中完成。
也就是有多个线程发消息,有多个消息队列在不同的线程中,分别在各自的线程中处理消息。
Windows的消息模型比较简单,但是全局的消息队列容易成为程序的瓶颈。
Looper类
looper是线程的消息循环处理器,每个线程只能有一个Looper对象,其内部有一个MessageQueue,所有消息都存放在这个队列中。新创建一个线程时,系统不会为这个线程创建Looper,需要自己创建。Android在启动时,为主线程(UI线程——创建了一个looper对象)。
我们先看一下HandlerThread线程,其就是继承了一个普通的线程,提供了一个消息队列和消息相应代码的运行环境。
public class HandlerThread extends Thread { int mPriority; int mTid = -1; Looper mLooper; public HandlerThread(String name) { super(name); mPriority = Process.THREAD_PRIORITY_DEFAULT; } public HandlerThread(String name, int priority) { super(name); mPriority = priority; } protected void onLooperPrepared() { } @Override public void run() { mTid = Process.myTid(); Looper.prepare();//Looper类的实例必须通过prepare函数创建 synchronized (this) { mLooper = Looper.myLooper();//通过myLooper方法获取Looper对象 notifyAll(); } Process.setThreadPriority(mPriority); onLooperPrepared(); Looper.loop();//loop函数主要分发消息队列中的消息。 mTid = -1; } public Looper getLooper() { if (!isAlive()) { return null; } // If the thread has been started, wait until the looper has been created. synchronized (this) { while (isAlive() && mLooper == null) { try { wait(); } catch (InterruptedException e) { } } } return mLooper; } public boolean quit() { Looper looper = getLooper(); if (looper != null) { looper.quit(); return true; } return false; }}
下面我们主要看下Looper类中的loop方法:
public static void loop() { final Looper me = myLooper(); if (me == null) { throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread."); } final MessageQueue queue = me.mQueue;//消息队列 Binder.clearCallingIdentity(); final long ident = Binder.clearCallingIdentity(); for (;;) {//无线循环 Message msg = queue.next(); // might block if (msg == null) { // No message indicates that the message queue is quitting. return; }........ msg.target.dispatchMessage(msg);//分发消息...... msg.recycle(); } }
Handler类
Handler主要负责消息的发送和处理。在一个线程中可以只用一个Hander对象处理所以消息,也可以使用多个。
构造一个Handler对象,需要两个参数,线程的Looper对象和消息处理函数,如果不指定looper,会使用当前线程的looper对象
Handler发送消息的接口如下:
public final boolean sendMessage(Message msg)//不插队 { return sendMessageDelayed(msg, 0); } public final boolean sendEmptyMessage(int what)//只有一个消息ID { return sendEmptyMessageDelayed(what, 0); } public final boolean sendEmptyMessageDelayed(int what, long delayMillis) { Message msg = Message.obtain(); msg.what = what; return sendMessageDelayed(msg, delayMillis); } public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis) { Message msg = Message.obtain();//指定时间,只有消息ID,其实就是自己获取一个msg,再调用sendMessageAtTime msg.what = what; return sendMessageAtTime(msg, uptimeMillis); } public final boolean sendMessageDelayed(Message msg, long delayMillis)//延迟多少时间 { if (delayMillis < 0) { delayMillis = 0; } return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis); } public boolean sendMessageAtTime(Message msg, long uptimeMillis) { MessageQueue queue = mQueue; if (queue == null) { RuntimeException e = new RuntimeException( this + " sendMessageAtTime() called with no mQueue"); Log.w("Looper", e.getMessage(), e); return false; } return enqueueMessage(queue, msg, uptimeMillis); } public final boolean sendMessageAtFrontOfQueue(Message msg) {//非常紧急,希望尽快处理 MessageQueue queue = mQueue; if (queue == null) { RuntimeException e = new RuntimeException( this + " sendMessageAtTime() called with no mQueue"); Log.w("Looper", e.getMessage(), e); return false; } return enqueueMessage(queue, msg, 0); } private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) { msg.target = this;//注意msg.target都是handler,因此在消息线程的loop函数处理消息时,msg.target.dispatchMessage会回到handler。 if (mAsynchronous) { msg.setAsynchronous(true); } return queue.enqueueMessage(msg, uptimeMillis); }
所有的发送消息接口,最后都会调用MessageQueue类中enqueueMessage函数,参数除了消息外,就是一个时间。而MessageQueue类中enqueueMessage函数只是把消息插入到消息队列中的合适位置。
我们再来看看Handler类的一些Post类型的函数:
public final boolean post(Runnable r) { return sendMessageDelayed(getPostMessage(r), 0); } public final boolean postAtTime(Runnable r, long uptimeMillis) { return sendMessageAtTime(getPostMessage(r), uptimeMillis); } public final boolean postAtTime(Runnable r, Object token, long uptimeMillis) { return sendMessageAtTime(getPostMessage(r, token), uptimeMillis); } public final boolean postDelayed(Runnable r, long delayMillis) { return sendMessageDelayed(getPostMessage(r), delayMillis); } public final boolean postAtFrontOfQueue(Runnable r) { return sendMessageAtFrontOfQueue(getPostMessage(r)); }
也是调用的send函数,只是调用了getPostMessage函数:
private static Message getPostMessage(Runnable r) { Message m = Message.obtain(); m.callback = r; return m; }
创建了一个message对象,并且将Runable对象赋给了callback。
下面再来看看Handler对象的dispatchMessage就知道了:
public void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg);//如果msg自带了callback函数 } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg);//最后再调用Handler的handleMessage函数 } }
看看handleCallback函数就是调用了msg的回调函数:
private static void handleCallback(Message message) { message.callback.run(); }
Handler中removeMessages将消息队列中的消息去除:
public final void removeMessages(int what, Object object) { mQueue.removeMessages(this, what, object); }
最后总结下:首先消息机制需要一个线程环境,里面需要一个Looper对象,并且在线程的run函数中调用Looper.loop()函数。函数需要一个handler来发送和处理消息。Hander要有一个Looper对象,来指定其线程,还要实现handleMessage函数。
- Android消息机制 java常用类
- Android 消息机制(Java层)
- android消息机制 java层简介
- Android消息机制1-Handler(Java层)
- 《android framework常用api源码分析》之handler消息机制
- Android消息机制(Handler机制)
- android Handler机制 消息机制
- android消息机制——Handler类
- Android 消息处理机制
- Android消息机制
- android 消息机制
- Android消息机制(一)
- Android消息处理机制
- Android消息处理机制
- Android消息机制(一)
- Android 中的消息机制
- Android 消息通知机制
- Android消息机制学习
- centos 关闭防火强
- C++ hex和oct
- 解密系列(系统篇_PE结构详解笔记1)
- 《5》CentOS7.0+OpenStack+kvm云平台部署—配置Horizon
- 微信授权网页登陆,oauth
- Android消息机制 java常用类
- java基础集合操作工具类Collections简述(java集合四)
- 解密系列(系统篇_PE结构详解笔记2)
- 41.调用随机函数产生20个整数,并输出。
- JAVA中int转String类型有三种方法
- Java加密技术(四)非对称加密算法RSA
- ESX、vSphere、ESXI的区别
- c语言之sizeof函数
- 流实现int_string转换