Android中Handler原理
Handler主要是主线程和子线程通信。一般子线程中做一些耗时操作做完之后通知主线程来改动UI。
实际上android系统在Activity启动或者状态变化等都是通过Handler机制实现的。
首先进入到ActivityThread的main方法中
public static void main(String[] args) {
……
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
……
Looper.loop();
……
}
以下主要分析上面几句代码。
1. Looper.prepareMainLooper();
public static void prepareMainLooper() {
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper();
}
}
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));//为这个线程会新建一个Looper对象
}
Looper的构造函数例如以下
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);//Looper维护了一个消息队列
mRun = true;
mThread = Thread.currentThread();
}
小结:在调用完Loop.prepare后。就会为当前线程创建一个消息泵Looper,这个Looper维护了一个消息队列MessageQueue
2. sMainThreadHandler =thread.getHandler();
sMainThreadHandler是Handler对象。getHandler方法例如以下:
final Handler getHandler() {
return mH;
}
看到mH在前面定义为final H mH = new H();实际上H是继承自Handler。部分代码例如以下:
private class H extends Handler {
public static final int LAUNCH_ACTIVITY = 100;
public static final int PAUSE_ACTIVITY = 101;
……
public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
switch (msg.what) {
case LAUNCH_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
ActivityClientRecord r = (ActivityClientRecord)msg.obj;
r.packageInfo = getPackageInfoNoCheck(
r.activityInfo.applicationInfo, r.compatInfo);
handleLaunchActivity(r, null);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
……
}
……
}
小结:这里相当于平时在UI线程中创建一个Handler实现他的handlerMessage方法。
3.Looper.loop();
public static void loop() {
……
final MessageQueue queue = me.mQueue;
for (;;) {
Message msg = queue.next(); // might block
if (msg == null) {
return;
}
……
msg.target.dispatchMessage(msg);
……
msg.recycle();
}
}
小结:调用Looper.loop()。能够看到for循环。不停地从消息队列中取消息。然后分发msg.target.dispatchMessage(msg); 这里的msg.target就是Handler对象,指的是处理该Message的Handler。
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
调用dispatchMessage。假设Message设置了回调函数就运行回调,否则假设定义Handler的时候假设传进了回调函数就运行传进的回调,不然就会运行handlerMessage函数,能够看到是有优先级顺序的。系统处理的时候因为未设置回调,就会运行handlerMessage。
比方上面的当收到LAUNCH_ACTIVITY消息,就会运行handleLaunchActivity---- performLaunchActivity---- mInstrumentation.newActivity(cl,component.getClassName(), r.intent); -----mInstrumentation.callActivityOnCreate(activity,r.state); ----- activity.performCreate(icicle);
这样就运行到了我们平时所谓的Activity的入口onCreate方法。
到如今我们看到了Handler机制在android中的应用。
接下来分析一下handler和Looper是怎么关联起来的。
Handler的构造函数终于都会去运行
public Handler(Callback callback, boolean async) {
if (FIND_POTENTIAL_LEAKS) {
final Class<?
extends Handler> klass = getClass();
if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
(klass.getModifiers() & Modifier.STATIC) == 0) {
Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
klass.getCanonicalName());
}
}
mLooper = Looper.myLooper();//获取当前线程的Looper
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;//将Looper对象的消息队列传给Handler的成员,使得Handler就能够操作该消息循环
mCallback = callback;
mAsynchronous = async;
}
Message类例如以下
public final class Message implements Parcelable {
public int what;
public int arg1;
public int arg2;
……
Handler target; //每一个消息都有一个成员保存和他关联的Handler
Runnable callback;
}
接下来我们看一下调用handler的sendMessage送消息时发生了什么
public final boolean sendMessage(Message msg)
{
return sendMessageDelayed(msg, 0);
}
最后会运行到:
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;//在这里将this复制给Message的Handler成员。this也就是我们定义的handler对象。
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);//然后加入到消息队列里面
}
msg.target = this;所以就有了在loop消息循环函数中的msg.target.dispatchMessage(msg);来分发消息。因为多台就会运行我们实现的handlerMessage里面的代码。
Android中Handler原理的更多相关文章
- Android中Handler 、Thread和Runnable之间的关系
在多线程编程的时候,我们经常会用到Handler,Thread和Runnable这三个类,我们来看看这三个类之间是怎么样的关系? 首先说明Android的CPU分配的最小单元是线程,Handler一般 ...
- Android中Handler作用
在Android的UI开发中,我们经常会使用Handler来控制主UI程序的界面变化.有关Handler的作用,我们总结为:与其他线程协同工作,接收其他线程的消息并通过接收到的消息更新主UI线程的内容 ...
- Android中Handler使用浅析
1. Handler使用引出 现在作为客户,有这样一个需求,当打开Activity界面时,开始倒计时,倒计时结束后跳转新的界面(思维活跃的朋友可能立马想到如果打开后自动倒计时,就类似于各个APP的欢迎 ...
- Android中Handler的消息处理机制以及源码分析
在实际项目当中,一个很常见的需求场景就是在根据子线程当中的数据去更新ui.我们知道,android中ui是单线程模型的,就是只能在UI线程(也称为主线程)中更新ui.而一些耗时操作,比如数据库,网络请 ...
- Android 中 Handler 引起的内存泄露
在Android常用编程中,Handler在进行异步操作并处理返回结果时经常被使用.其实这可能导致内存泄露,代码中哪里可能导致内存泄露,又是如何导致内存泄露的呢?那我们就慢慢分析一下.http://w ...
- android中handler用法总结
一.Handler的定义: Handler主要接收子线程发送的数据, 并用此数据配合主线程更新UI,用来跟UI主线程交互用.比如可以用handler发送一个message,然后在handler的线程中 ...
- Android中Handler引起的内存泄露
在Android常用编程中,Handler在进行异步操作并处理返回结果时经常被使用.通常我们的代码会这样实现. 1 2 3 4 5 6 7 8 9 public class SampleActivit ...
- Android中Handler的使用
当我们在处理下载或是其他需要长时间执行的任务时,如果直接把处理函数放Activity的OnCreate或是OnStart中,会导致执行过程中整个Activity无响应,如果时间过长,程序还会挂掉.Ha ...
- Android中Handler的使用方法及实例(基础回顾)
Handler使用例1 这个例子是最简单的介绍handler使用的,是将handler绑定到它所建立的线程中.本次实验完成的功能是:单击Start按钮,程序会开始启动线程,并且线程程序完成后延时1s会 ...
随机推荐
- spring batch(一):基础部分
spring batch(一):基础部分 博客分类: Spring java spring batch 官网: http://www.springsource.org/spring-batch 下 ...
- 2015.04.23,外语,读书笔记-《Word Power Made Easy》 12 “如何奉承朋友” SESSION 33
1.eat, drink, and be merry 拉丁动词vivo(to live),加上名词vita(life),是许多重要英文词汇的来源. convivo是拉丁动词to live togeth ...
- listView 多个item布局
package kds.szkingdom.wo.android.adapter; import java.util.List; import android.content.Context; imp ...
- ActiveX插件
C#制作ActiveX插件 首先新建项目--->类库,取名:ActiveXDemo 右键项目属性:应用属性==>程序集信息=>使程序集Com可见, 生成==>输出==>为 ...
- Java类的根Object
一.Object类介绍 Object全名java.lang.Object,java.lang包在使用的时候无需显示导入,编译时由编译器自动导入.Object类是类层次结构的根,Java中所有的类从根本 ...
- 8.QList QMap QVariant
QList int main1(int argc, char *argv[]) { QApplication a(argc, argv); QList<,,}; mylist << ...
- 基本类型转换成NSNumber类型
int i=100; float f=2.34; NSNumber *n1=[NSNumber numberWithInt:i]; NSNumber *n2=[NSNumber numberWithF ...
- ROS-opencv-人脸识别-物体追踪-二维码识别
前言:人脸识别是基于人的脸部特征信息进行身份识别的一种生物识别技术.用摄像机或摄像头采集含有人脸的图像或视频流,并自动在图像中检测和跟踪人脸,进而对检测到的人脸进行脸部识别的一系列相关技术,通常也叫做 ...
- GRpc-Go使用笔记
linux下配置GRpc-golang 1.git中下载protobuf包 2.解压(/usr/local/protobuf) unzip protobuf-cpp-3.0.0-alpha-3.z ...
- C/C++函数调用约定与this指针
关于 C/C++ 函数调用约定,大多数时候并不会影响程序逻辑,但遇到跨语言编程时,了解一下还是有好处的. VC 中默认调用是 __cdecl 方式,Windows API 使用 __stdcall 调 ...