Android中Handler原理

来源:互联网 发布:南京淘宝兼职模特招聘 编辑:程序博客网 时间:2024/05/18 03:46

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里面的代码。

6 1
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 我微信冻结了怎么办 微信账号冻结了怎么办 微信被冻结里面的钱怎么办 微信账户冻结了怎么办 微信公众号忘记密码怎么办 网课没有刷完怎么办 形势与政策挂了怎么办 苹果录屏声音小怎么办 老师跟学生家长吵起来了怎么办 蓝幕拍摄抠像有蓝色怎么办 学东西悟性不高怎么办 微商不会写笔记怎么办 布鞋买大了一码怎么办 凉鞋买大了一码怎么办 皮鞋小了一码怎么办妙招 图书馆借的书本损坏了怎么办 把人打伤没钱赔怎么办 小孩不小心打伤了老师怎么办 高考进了三段怎么办 工作中和领导产生冲突怎么办 酒店不给员工发工资怎么办 裙子没有解开超市的锁怎么办 接待老外听不懂他说的怎么办 脚脱皮又痒又臭怎么办 成都应聘平面模特被骗了怎么办 文明6开场一堆蛮族怎么办 幼儿园里出了水痘怎么办 穿高跟鞋脚容易出汗怎么办 粗跟鞋走路太响怎么办 粗跟鞋鞋跟很响怎么办 皮鞋跟走路太响怎么办 穿高跟鞋脚崴了怎么办 高跟鞋小了一码怎么办 高跟皮鞋磨脚怎么办 大同同煤集团三供一业人员怎么办 小孩被猫咪抓了怎么办 长得特别丑的人怎么办 锅巴放的不脆了怎么办 淘宝买到假货了怎么办 单位不给解约函怎么办 安卓个人热点打不开怎么办