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原理的更多相关文章

  1. Android中Handler 、Thread和Runnable之间的关系

    在多线程编程的时候,我们经常会用到Handler,Thread和Runnable这三个类,我们来看看这三个类之间是怎么样的关系? 首先说明Android的CPU分配的最小单元是线程,Handler一般 ...

  2. Android中Handler作用

    在Android的UI开发中,我们经常会使用Handler来控制主UI程序的界面变化.有关Handler的作用,我们总结为:与其他线程协同工作,接收其他线程的消息并通过接收到的消息更新主UI线程的内容 ...

  3. Android中Handler使用浅析

    1. Handler使用引出 现在作为客户,有这样一个需求,当打开Activity界面时,开始倒计时,倒计时结束后跳转新的界面(思维活跃的朋友可能立马想到如果打开后自动倒计时,就类似于各个APP的欢迎 ...

  4. Android中Handler的消息处理机制以及源码分析

    在实际项目当中,一个很常见的需求场景就是在根据子线程当中的数据去更新ui.我们知道,android中ui是单线程模型的,就是只能在UI线程(也称为主线程)中更新ui.而一些耗时操作,比如数据库,网络请 ...

  5. Android 中 Handler 引起的内存泄露

    在Android常用编程中,Handler在进行异步操作并处理返回结果时经常被使用.其实这可能导致内存泄露,代码中哪里可能导致内存泄露,又是如何导致内存泄露的呢?那我们就慢慢分析一下.http://w ...

  6. android中handler用法总结

    一.Handler的定义: Handler主要接收子线程发送的数据, 并用此数据配合主线程更新UI,用来跟UI主线程交互用.比如可以用handler发送一个message,然后在handler的线程中 ...

  7. Android中Handler引起的内存泄露

    在Android常用编程中,Handler在进行异步操作并处理返回结果时经常被使用.通常我们的代码会这样实现. 1 2 3 4 5 6 7 8 9 public class SampleActivit ...

  8. Android中Handler的使用

    当我们在处理下载或是其他需要长时间执行的任务时,如果直接把处理函数放Activity的OnCreate或是OnStart中,会导致执行过程中整个Activity无响应,如果时间过长,程序还会挂掉.Ha ...

  9. Android中Handler的使用方法及实例(基础回顾)

    Handler使用例1 这个例子是最简单的介绍handler使用的,是将handler绑定到它所建立的线程中.本次实验完成的功能是:单击Start按钮,程序会开始启动线程,并且线程程序完成后延时1s会 ...

随机推荐

  1. codeforces 571A--Lengthening Sticks(组合+容斥)

    A. Lengthening Sticks time limit per test 1 second memory limit per test 256 megabytes input standar ...

  2. EasyUI----动态拼接EasyUI控件

    近期在做的项目中.依据查询到的数据,然后动态的拼接easyUI的控件显示到界面上. 在数据库中,有一个命令的表,另一个參数的表,先到命令的表中去查询这一个设备有哪些命令,比方说.摄像头有一个转动的命令 ...

  3. tapestry3创建自己定义组件

    两种方法创建自己定义标签: 一.通过AbstractComponent父类渲染,此种方法直接在java类中编写页面脚本.然后输出. 1.编写java类com/ailk/ech/ecop/view/te ...

  4. ym—— Android网络框架Volley(终极篇)

    转载请注明本文出自Cym的博客(http://blog.csdn.net/cym492224103).谢谢支持! 没看使用过Volley的同学能够,先看看Android网络框架Volley(体验篇)和 ...

  5. CodeForces--609C --Load Balancing(水题)

    Load Balancing Time Limit: 2000MS   Memory Limit: 262144KB   64bit IO Format: %I64d & %I64u Subm ...

  6. hdoj--2534--Score(gcd)

    Score Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Subm ...

  7. 原生javascript实现文件异步上传

    效果图: 代码:(demo33.jsp) <%@ page contentType="text/html;charset=UTF-8" language="java ...

  8. 打包phar文件过大的问题。

    根据一个开源工具得到的灵感,使用流打包,并使用token_get_all移除了所用PHP文件的空白.现在打包出来只有93k了.谢谢关注. 我一个简单的文件,加上一个symfony的process包,打 ...

  9. 分享一个完美的新闻客户端(酷商城)Android源码

    分享一个完美的新闻客户端(酷商城)Android源码,这个源码项目是从安卓教程网转载过来的,项目主要是解析html,fragment,异步缓存图片加载,webview加载网页等.可以正常的运行的,我已 ...

  10. oc与swift比较

    swift试是用语言层面的雕虫小技和oc的机制大道进行pk. 从整体上来说,oc是一个更加优秀的语言.