Android系统Handler消息处理机制(一)
2017-02-28 22:29
501 查看
前言:
我接触Handler第一次的时候就比较懵逼,Handler handler=new Handler()然后调用handler.sendEmptyMessage();就可以发送消息了,然后在Handler的回调中处理消息.当时只是单纯觉得是一个消息队列,从这边发送消息,那边是一个死循环接收消息,然后调用回调函数打印.仔细没多想,现在具体想了一下,看了源码,才知道并不是那么简单.那么具体那些问题需要思考呢?
1.队列到哪里?谁又在取消息分发?
2.死循环到底怎么一个循环法.
3.还有很多人误解的为什么主线程不会因为Looper.loop()里的死循环卡死?
…
带着这些问题,我们今天就具体看看源码怎么说
Looper
我们知道Looper类是一个线程的消息循环处理器1.Looper构造方法私有.
2.Looper对象每个线程只能有一个.
3.并且通过静态prepare方法创建.
4.保存在
ThreadLocal<Looper> sThreadLocal中(是一个线程有关的键值对存取容器)
private Looper(boolean quitAllowed) { mQueue = new MessageQueue(quitAllowed); mThread = Thread.currentThread(); }
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)); }
我们下来看看Looper类的loop方法
public static void loop() { final Looper me = myLooper();//得到当前线程的looper if (me == null) { throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread."); } final MessageQueue queue = me.mQueue;//从looper中拿出消息队列 Binder.clearCallingIdentity(); final long ident = Binder.clearCallingIdentity(); for (;;) { Message msg = queue.next(); //进行遍历消息队列 if (msg == null) { return; } Printer logging = me.mLogging; msg.target.dispatchMessage(msg);//拿到Handler进行分发事件 final long newIdent = Binder.clearCallingIdentity(); msg.recycleUnchecked(); } } public static @Nullable Looper myLooper() { return sThreadLocal.get(); }
loop()中就做了4个事情
1.得到当前线程的looper
2.从looper中拿出消息队列
3.进行遍历消息队列
4.拿到Handler进行分发事件
这里思考一个问题:既然知道
ThreadLocal<Looper> sThreadLocal是一个拿取当前线程的Looper类,那么当前线程是在哪?
这里看下Handler的构造:
public Handler(Callback callback, boolean async) { ... mLooper = Looper.myLooper(); if (mLooper == null) { throw new RuntimeException( "Can't create handler inside thread that has not called Looper.prepare()"); } mQueue = mLooper.mQueue; ... }
可以看出来我们一般使用在Activity中创建Handler然后发送消息,所以Handler中得到的也是Activity的线程.
问题来了:Activity的线程大家都说是UI线程,但是也没有人具体说怎么UI了,在哪里UI了,下面我就带大家溜溜源码.
图片出自Android系统大牛Gityuan:Activity启动流程篇:
http://gityuan.com/2016/03/12/start-activity/
具体我们看一看目标进程中的哪里创建了Activity对象
//ApplicationThread.java public final void scheduleLaunchActivity(...) { ... sendMessage(H.LAUNCH_ACTIVITY, r); }
public void handleMessage(Message msg) { switch (msg.what) { case LAUNCH_ACTIVITY: { ... handleLaunchActivity(r, null); } break; ... } }
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) { ... Activity a = performLaunchActivity(r, customIntent); ... }
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) { ... Activity activity = null; java.lang.ClassLoader cl = r.packageInfo.getClassLoader(); //通过反射创建Activity activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent); //下面就是调用各种Activity的生命周期回调方法 activity.attach(...); mInstrumentation.callActivityOnCreate(activity, r.state); activity.performStart(); mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,r.persistentState); mInstrumentation.callActivityOnPostCreate(activity, r.state,r.persistentState); mInstrumentation.callActivityOnPostCreate(activity, r.state); return activity; }
上面过程我们看出来是ApplicationThread类sendMessage(H.LAUNCH_ACTIVITY,r);在handleMessage的分发事件中创建出来了Activity对象,所以这个问题归结于这个分发事件在那个进程的那个线程中跑.
来看,首先发给消息的Handler是在ActivityThread类中创建的H对象
private class H extends Handler { public static final int LAUNCH_ACTIVITY = 100;
也就是说,在Activity中的Looper对象是在ActivityThread所在的线程中.
那我们就来看看ActivityThread在那个线程中,我们看看ActivityThread创建的main方法
public static void main(String[] args) { ... Looper.prepareMainLooper();//创建属于此线程的Looper ActivityThread thread = new ActivityThread(); thread.attach(false); ... Looper.loop(); }
public static void prepareMainLooper() { prepare(false); ... }
private static void prepare(boolean quitAllowed) { ... sThreadLocal.set(new Looper(quitAllowed)); }
到了这里我们惊喜的发现在ActivityThread的main()方法中创建了主线程的Looper,并且Activity和ActivityThread在同一个线程,即主线程
总结:
1.Looper类是Android中线程消息通信的重要类,扮演线程消息的处理器的角色2.每个线程只能创建一个Looper对象
3.通过Looper.prepare()方法创建Looper对象,Looper.prepareMainLooper();创建主线程Looper对象
4.有了Looper对象用loop方法进入消息循环
5.loop方法不断从MessageQueue队列中拿出消息,然后分发给Handler的回调方法
6.一个Looper可以对应多个Handler对象
7.Looper方法在存取每个线程所属于的私有变量是通过ThreadLocal成员
8.在Activity中创建的Handler对象,中创建的Looper是和ActivityThread在一个线程中即主线程
下一节我们分析Handler,Message等其他有关重要的类
相关文章推荐
- Android系统Handler消息处理机制(二)
- Android系统分析之异步消息处理机制-Message/Handler/MessageQueue/Looper
- 深入理解Android消息处理系统——Looper、Handler、Thread
- 深入理解Android消息处理系统——Looper、Handler、Thread
- 深入理解Android消息处理系统——Looper、Handler、Thread
- Android消息处理机制:Handler Thread Message Looper []
- 深入理解Android消息处理系统——Looper、Handler、Thread
- 深入理解Android消息处理系统——Looper、Handler、Thread
- 深入理解Android消息处理系统——Looper、Handler、Thread
- 【转】深入理解Android消息处理系统——Looper、Handler、Thread
- 深入理解Android消息处理系统——Looper、Handler、Thread
- 深入理解Android消息处理系统——Looper、Handler、Thread
- Android消息处理机制:Handler Thread Message Looper
- 深入理解Android消息处理系统——Looper、Handler、Thread
- 深入理解Android消息处理系统——Looper、Handler、Thread
- (转)深入理解Android消息处理系统——Looper、Handler、Thread
- 深入理解Android消息处理系统——Looper、Handler、Thread
- Android消息处理机制:Handler Thread Message Looper
- 深入理解Android消息处理系统——Looper、Handler、Thread
- 深入理解Android消息处理系统——Looper、Handler、Thread