Android----Handler机制剖析
来源:互联网 发布:自动备份短信软件 编辑:程序博客网 时间:2024/06/05 08:28
主线程: 也叫UI线程,或称ActivityThread,用于运行四大组件和处理他们用户的交互。ActivityThread管理应用进程的主线程的执行(相当于普通Java程序的main入口函数),在Android系统中,在默认情况下,一个应用程序内的各个组件(如Activity、BroadcastReceiver、Service)都会在同一个进程(Process)里执行,且由此进程的主线程负责执行。 ActivityThread既要处理Activity组件的UI事件,又要处理Service后台服务工作,通常会忙不过来。为了解决此问题,主线程可以创建多个子线程来处理后台服务工作,而本身专心处理UI画面的事件。子线程: 用于执行耗时操作,比如 I/O操作和网络请求等。(安卓3.0以后要求耗访问网络必须在子线程种执行)更新UI的工作必须交给主线程,子线程在安卓里是不允许更新UI的。1.在讲Handler机制之前,首先介绍下以下几个对象Message:消息,其中包含了消息ID,消息处理对象以及处理的数据等,由MessageQueue统一列队,终由Handler处理。
Handler:处理者,负责将Message添加到消息队列以及对消息队列中的Message进行处理。使用Handler时,需要实现handleMessage(Message msg)方法来对特定的Message进行处理,例如更新UI等。
MessageQueue:消息队列,用来存放Handler发送过来的消息,按照先进先出执行。当然,存放Message并非实际意义的保存,而是将Message以链表的方式串联起来的,等待Looper的抽取。
Looper: 循环器,扮演Message Queue和Handler之间桥梁的角色,循环取出Message Queue里面的Message,并交付给相应的Handler进行处理。因此,一个MessageQueue需要一个Looper。
Thread:线程,负责调度整个消息循环,即消息循环的执行场所。
2.接下来讲讲Handler,Looper和MessageQueue这三者的关系
Looper和MessageQueue一一对应,创建一个Looper的同时,会创建一个MessageQueue。
Handler与它们的关系,只是简单的聚集关系,即Handler里会引用当前线程里的特定Looper和MessageQueue。
这样说来,多个Handler都可以共享同一Looper和MessageQueue了。
这些Handler也就运行在同一个线程里,每个线程一个Loop,一个MessageQueue。
3.Handler主要用于异步消息的处理:当发出一个消息之后,首先进入一个消息队列,发送消息的函数即刻返回,而另外一个部分在消息队列中逐一将消息取出,然后对消息进行处理,也就是发送消息和接收消息不是同步的处理。 这种机制通常用来处理相对耗时比较长的操作。
3.1 Handler的定义:主要接受子线程发送的数据, 并用此数据配合主线程更新UI。
解释:当应用程序启动时,Android首先会开启一个主线程 (也就是UI线程) , 主线程为管理界面中的UI控件, 进行事件分发, 比如说, 你要是点击一个 Button ,Android会分发事件到Button上,来响应你的操作。 如果此时需要一个耗时的操作,例如: 联网读取数据, 或者读取本地较大的一个文件的时候,你不能把这些操作放在主线程中,如果你放在主线程中的话,界面会出现假死现象, 如果5秒钟还没有完成的话,会收到Android系统的一个错误提示 "强制关闭"。 这个时候我们需要把这些耗时的操作,放在一个子线程中,因为子线程涉及到UI更新,,Android主线程是线程不安全的, 也就是说,更新UI只能在主线程中更新,子线程中操作是危险的。 这个时候,Handler就出现了。,来解决这个复杂的问题 ,由于Handler运行在主线程中(UI线程中), 它与子线程可以通过Message对象来传递数据, 这个时候,Handler就承担着接受子线程传过来的(子线程用sedMessage()方法传弟)Message对象,(里面包含数据) , 把这些消息放入主线程队列中,配合主线程进行更新UI。3.2 Handler一些特点
handler可以分发Message对象和Runnable对象到主线程中, 每个Handler实例,都会绑定到创建他的线程中(一般是位于主线程),它有两个作用:
(1)安排消息或Runnable 在某个主线程中某个地方执行;
(2)安排一个动作在不同的线程中执行。3.3 Handler实例
子类需要继承Handler类,并重写handleMessage(Message msg) 方法, 用于接受线程数据4.1 创建消息:Handler创建消息时首先查询消息池中是否有消息存在,如果有直接从消息池中取得,如果没有则重新初始化一个消息实例。使用消息池的好处:消息不被使用时,并不作为垃圾回收,而是放入消息池,可供下次Handler创建消息时使用。消息池提高了消息对象的复用,减少系统垃圾回收的次数。4.2 发送消息:UI主线程初始化第一个Handler时会通过ThreadLocal创建一个Looper,该Looper与UI主线程一一对应。使用ThreadLocal的目的是保证每一个线程只创建唯一一个Looper。之后其他Handler初始化的时候直接获取第一个Handler创建的Looper。Looper初始化的时候会创建一个消息队列MessageQueue。Hander持有对UI主线程消息队列MessageQueue和消息循环Looper的引用,子线程可以通过Handler将消息发送到UI线程的消息队列MessageQueue中。4.3 处理消息:UI主线程通过Looper循环查询消息队列,当发现有消息存在时会将消息从消息队列中取出。首先分析消息,通过消息的参数判断该消息对应的Handler,然后将消息分发到指定的Handler进行处理。5.Handler机制使用流程5.1 Handler机制是Android提供的一种异步回调机制,在Ui线程中使用handler需要new一个handler对象,并重写其中的handleMessage(Message msg)方法,处理如更新UI等操作。
private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
//to do
}
};
5.2 在异步线程中调用hanlder.sendMessage(Message msg)告诉UI线程去更新UI等操作。从原理上来讲,使用了Hanlder对象的线程需要绑定一个Looper对象,该对象维护一个消息队列,Looper对象取出该队列的消息后交由handler进行处理。所以在使用Handler时,要调用Looper.prepare()方法给当前的线程绑定一个Looper对象。
public static void prepare() {
prepare(true);
}
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
然后调用loop()建立对消息队列的循环,在消息队列中取出消息后交由相应的handler进行处理。由于一个线程中可能有多个handler,为了区分这些不同的hanlder所需要处理的消息,每个Message对象都维护有一个hanlder实例即target,在loop方法中通过调用msg.target.dispatchMessage(msg)进行处理。
每个线程只能绑定一个loop对象,多个handler共享,handler的在构造时从当前的线程中取得loop对象,Looper中的myLooper中返回了sThreadLocal.get()所取得的Looper对象
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
所以,在使用handler中需要执行以下步骤,首先调用Looper.prepare()方法为当前线程绑定Looper对象,然后才可以实例化一个Handler对象,最后调用loop()方法建立消息循环
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();
}
}
在很多情况下我们在activity或者其他场合中使用Handler进行异步消息处理,并没有显式地声明绑定一个Looper对象。这是因为主线程它已经绑定了一个Looper对象
public static final void main(String[] args) {
SamplingProfilerIntegration.start();
Process.setArgV0("<pre-initialized>");
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
Looper.loop();
if (Process.supportsProcesses()) {
throw new RuntimeException("Main thread loop unexpectedly exited");
}
thread.detach();
String name = (thread.mInitialApplication != null)
? thread.mInitialApplication.getPackageName()
: "<unknown>";
Slog.i(TAG, "Main thread of " + name + " is now exiting");
}
想更清楚的了解Handler机制,请参考以下资料:http://www.jianshu.com/p/9e4d1fab0f36http://www.cnblogs.com/JczmDeveloper/p/4403129.htmlhttp://blog.csdn.net/ljd2038/article/details/50889754http://blog.csdn.net/lmj623565791/article/details/38377229/
- Android Handler机制剖析
- Android Handler机制剖析
- Android----Handler机制剖析
- 剖析Android-Handler机制流程
- Android源码剖析之-------Handler机制详解
- Android中消息处理机制-Handler剖析
- Android的线程消息机制(Handler机制剖析)
- Handler机制剖析
- Android消息机制原理剖析—Handler篇
- Android 消息机制之 handler、messageQueue、looper深入剖析
- android中handler消息发送机制源码剖析
- 深度剖析handler消息机制
- Android Handler源码剖析
- 从子线程不能直接新建一个Handler对象来剖析android的Handler机制
- 【Android 开发】: Android 消息处理机制之三: Handler 中 sendMessage() 源代码剖析
- 【Android 开发】: Android 消息处理机制之三: Handler 中 sendMessage() 源代码剖析
- 【Android 开发】: Android 消息处理机制之三: Handler 中 sendMessage() 源代码剖析
- 【Android 开发】: Android 消息处理机制之三: Handler 中 sendMessage() 源代码剖析
- python实例(分解质因数)
- ssh整合项目启动报错Context initialization failed org.springframework.beans.factory.BeanCreationException
- 数论入门--错排
- yii2 console相关
- 常用文件复制方法
- Android----Handler机制剖析
- 盘点国内6大抗DDOS攻击服务商
- 阿里语音识别(语音转文字)java调用全程手把手详解-适合中小学生快速上手
- 安卓打包时遇到方法过多的问题
- Android 调用相机拍摄照片或者从相册选取照片
- margin:0 auto 表示什么意思??
- 人工智能之机器学习算法体系汇总
- 反思2017
- 在移动端单行文本在不同的屏幕下当文本过长时增加省略号效果