android分析之消息处理

前序:每个APP对应一个进程,该进程内有一个ActivityThread的线程,称为主线程(即UI主线程),此外,还有其他线程,这个再论。

android的消息系统分析。

  1. 每个Thread只对应一个Looper
  2. 每个Looper只对应一个MessageQueue
  3. 每个MessageQueue中有N个Message
  4. 每个Message中最多指定一个Handler来处理事件
  5. 一个Thread可以对应多个Handler

Looper负责从消息队列中(MessageQueue)取出消息(Message/Runnable),交给Handler来处理。

Message:

public final class Message implements Parcelable {
    public int what;//每个Message可以指定一个Handler,由于可以存在多个Handler,用what来标识具体的Handler

    public int arg1;
    public int arg2;
    public Object obj;
    public Messenger replyTo;

    /*package*/ static final int FLAG_IN_USE = 1 << 0;

    /*package*/ static final int FLAG_ASYNCHRONOUS = 1 << 1;

    /*package*/ static final int FLAGS_TO_CLEAR_ON_COPY_FROM = FLAG_IN_USE;

    /*package*/ int flags;

    /*package*/ long when;

    /*package*/ Bundle data;

    /*package*/ Handler target;//指定由哪个Handler来处理本Message

    /*package*/ Runnable callback;   

    /*package*/ Message next;//消息链

    private static final Object sPoolSync = new Object();
    private static Message sPool;//消息链表的头,注意是static
    private static int sPoolSize = 0;

    private static final int MAX_POOL_SIZE = 50;

......

}

MessageQueue实际上是对Message的一种操作的封装,真正的消息队列是以sPool为首的消息链表:

public class MessageQueue {
    // True if the message queue can be quit.
    private final boolean mQuitAllowed;

    @SuppressWarnings("unused")
    private int mPtr; // used by native code

    Message mMessages;//消息...
    private final ArrayList<IdleHandler> mIdleHandlers = new ArrayList<IdleHandler>();
    private IdleHandler[] mPendingIdleHandlers;
    private boolean mQuiting;

    // Indicates whether next() is blocked waiting in pollOnce() with a non-zero timeout.
    private boolean mBlocked;

    // The next barrier token.
    // Barriers are indicated by messages with a null target whose arg1 field carries the token.
    private int mNextBarrierToken;
//调用Native函数做真正的处理
    private native void nativeInit();
    private native void nativeDestroy();
    private native void nativePollOnce(int ptr, int timeoutMillis);
    private native void nativeWake(int ptr);......

}

  Looper:

public class Looper {
    private static final String TAG = "Looper";

    static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();//与线程相关的模板类
    private static Looper sMainLooper;  //static类型,只有一个

    final MessageQueue mQueue;//Looper持有的MessageQueue
    final Thread mThread;
    volatile boolean mRun;

    private Printer mLogging;

......

}

  

Handler:

public class Handler{//真正对处理Message的类:包括处理Message和将消息压到MessageQueue队列里

    final MessageQueue mQueue;
    final Looper mLooper;
    final Callback mCallback;
    IMessenger mMessenger;

...

}

  

Looper的loop()循环:

    public static void loop() {
        final Looper me = myLooper();
        if (me == null) {
            throw new RuntimeException("No Looper; Looper.prepare() wasn‘t called on this thread.");
        }
        final MessageQueue queue = me.mQueue;

        Binder.clearCallingIdentity();
        final long ident = Binder.clearCallingIdentity();

        for (;;) {//消息循环
            Message msg = queue.next(); // might block//取得一个消息
            if (msg == null) {//消息体为空则表示退出
                // No message indicates that the message queue is quitting.
                return;
            }

            // This must be in a local variable, in case a UI event sets the logger
            Printer logging = me.mLogging;
            if (logging != null) {
                logging.println(">>>>> Dispatching to " + msg.target + " " +
                        msg.callback + ": " + msg.what);
            }

            msg.target.dispatchMessage(msg);//调用消息指定的接收者Handler来处理它

            if (logging != null) {
                logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
            }

            // Make sure that during the course of dispatching the
            // identity of the thread wasn‘t corrupted.
            final long newIdent = Binder.clearCallingIdentity();
            if (ident != newIdent) {
                Log.wtf(TAG, "Thread identity changed from 0x"
                        + Long.toHexString(ident) + " to 0x"
                        + Long.toHexString(newIdent) + " while dispatching to "
                        + msg.target.getClass().getName() + " "
                        + msg.callback + " what=" + msg.what);
            }

            msg.recycle();//丢弃消息,循环再利用
        }
    }

  Handler取消息,每次从sPool(Message里的static Message类型)取出一个Message,其调用的是static方法:

    public static Message obtain(Handler h, int what, Object obj) {
        Message m = obtain();
        m.target = h;
        m.what = what;
        m.obj = obj;

        return m;
    }

  Handler将消息压入消息队列:

    public boolean sendMessageAtTime(Message msg, long uptimeMillis)
    {
        boolean sent = false;
        MessageQueue queue = mQueue;
        if (queue != null) {
            msg.target = this;
            sent = queue.enqueueMessage(msg, uptimeMillis);//调用MessageQueue的方法执行压入操作
        }
        else {
            RuntimeException e = new RuntimeException(
                this + " sendMessageAtTime() called with no mQueue");
            Log.w("Looper", e.getMessage(), e);
        }
        return sent;
    }

  小结:Handler取消息是直接取(从sPool里),将消息压入MessageQueue是调用MessageQueue的方法。

----------------------------------------------分割线----------------------------------------------------------------------------

下面分析这些对象都是在什么时候创建的。

Looper是什么时候创建的?

每个线程都只有一个Looper对象。

1.普通线程(非主线程)

一个典型的自己创建的线程使用Looper如:

class LooperThread extends Thread{
    public Handler mHandler;
    public void run(){
        Looper.prepare();
        mHandler= new Handler(){
                public void handleMessage(Message msg){
                    //处理消息
                }
        };
        Looper.loop();//进入消息循环
    }
}

  那么Looper是在什么时候创建的呢?看Looper.prepare()方法:执行完这个方法,就得到了一个本线程独有的Looper。

static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();//这是一个与线程先关的模板类    

private static void prepare(boolean quitAllowed) {
        if (sThreadLocal.get() != null) {//若调用者所在宿主线程已经有Looper,则抛出异常
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper(quitAllowed));//Java中的线程局部存储,即不同线
    }//程都通过sThreadLocal得到自己的不同的Looper对象引用
    private Looper(boolean quitAllowed) {
        mQueue = new MessageQueue(quitAllowed);//创建Looper要处理的消息队列
        mRun = true;
        mThread = Thread.currentThread();//得到当前线程
    }

  

  那么Handler是如何与Looper关联起来的呢?看Handler的构造方法:

public Handler() {
        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;
        mCallback = null;
    }
    public static Looper myLooper() {//获取与本线程相关的Looper
        return sThreadLocal.get();
    }

  

  小结:每个线程都通过sThreadLocal<Looper>来创建一个Looper(进而创建一个MessageQueue),再创建一个Handler(通过sThreadLocal),从而将Handler与Looper“绑定”在一起,形成一个完整的消息循环系统。

2.主线程ActivityThread

主线程是什么时候创建Looper的?在ActivityThread.java的main方法里有:

    public static void main(String[] args) {
        SamplingProfilerIntegration.start();
        CloseGuard.setEnabled(false);

        Process.setArgV0("<pre-initialized>");

        Looper.prepareMainLooper();//也是sThreadLocal.set(new Looper(quitAllowed))来创建一个线程所属的Looper,并通过sThreadLocal.get()将Looper赋给sMainLooper(private static Looper sMainLooper),sMainLooper的作用就是,其他线程可以获取到主线程的Looper(因为sMainLooper是static,在主线程中赋值的)。
        if (sMainThreadHandler == null) {
            sMainThreadHandler = new Handler();
        }

        ActivityThread thread = new ActivityThread();
        thread.attach(false);

        AsyncTask.init();

        if (false) {
            Looper.myLooper().setMessageLogging(new
                    LogPrinter(Log.DEBUG, "ActivityThread"));
        }

        Looper.loop();

        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

  

Looper.loop()是一个static的方法,作为消息循环处理器,不断的取消息,分发消息。

时间: 2024-10-29 10:45:41

android分析之消息处理的相关文章

Android中的消息处理实例与分析

Android中的消息处理实例与分析 摘要 本文介绍了Android中的消息处理机制,给出了Android消息处理中的几个重点类Handler.Message.MessageQueue.Looper.Runnable.Thread的详细介绍,提供了两个消息处理的实例代码,并深入分析了使用Android消息机制应该遵循的几个原则. 阅读本文的收获 在具有java基础的情况下,Android的学习比较轻松,很多人在没有深刻了解Android消息处理机制的背景下,已经能够开发出可用的app,很多人开始

从Handler+Message+Looper源代码带你分析Android系统的消息处理机制

PS一句:不得不说CSDN同步做的非常烂.还得我花了近1个小时恢复这篇博客. 引言 [转载请注明出处:http://blog.csdn.net/feiduclear_up CSDN 废墟的树] 作为Android开发人员,相信非常多人都使用过Android的Handler类来处理异步任务. 那么Handler类是怎么构成一个异步任务处理机制的呢?这篇 博客带你从源代码分析Android的消息循环处理机制.便于深入的理解. 这里不得不从"一个Bug引发的思考"開始研究Android的消息

从Handler+Message+Looper源码带你分析Android系统的消息处理机制

引言 [转载请注明出处:从Handler+Message+Looper源码带你分析Android系统的消息处理机制 CSDN 废墟的树] 作为Android开发者,相信很多人都使用过Android的Handler类来处理异步任务.那么Handler类是怎么构成一个异步任务处理机制的呢?这篇 博客带你从源码分析Android的消息循环处理机制,便于深入的理解. 这里不得不从"一个Bug引发的思考"开始研究Android的消息循环处理机制.说来话长,在某一次的项目中,原本打算开启一个工作线

Android Handler 异步消息处理机制的妙用 创建强大的图片加载类

转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/38476887 ,本文出自[张鸿洋的博客] 最近创建了一个群,方便大家交流,群号:55032675 上一篇博客介绍了Android异步消息处理机制,如果你还不了解,可以看:Android 异步消息处理机制 让你深入理解 Looper.Handler.Message三者关系 .那篇博客的最后,提出可以把异步消息处理机制不仅仅是在MainActivity中更新UI,可以用到别的地方,

cocos android分析

cocos2d-x Android环境搭建 cocos2d-x环境搭建比较简单,但是小问题还是不少,我尽量都涵盖的全面一些. 下载软件 cygwin.NDK(ADT):C++相关 如果之前没有Android开发环境,还需要Android SDK,Eclipse cocos2d-x源码 我的环境为ndk r7,cygwin1.7,Android SDK为2.2和3.0.另外,我是通过真机调试,在模拟器上不行,估计还是我T410显卡的问题. 安装cygwin,在cygwin文件进行路径设置 在cyg

Android分析第三方应用layout的神器

hierarchyviewer.bat或者monitor.bat一直都是分析layout的神器,不过,很多时候不好用,连不上真机,害的我不得不使用模拟器来分析layout. 今天发现了另外一个申请,就在ADT里面,它就躺在那,我怎么一直就没发现? Dump View Hierarchy for UI Automator Android分析第三方应用layout的神器

Android应用程序消息处理机制(Looper、Handler)分析

文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6817933 Android应用程序是通过消息来驱动的,系统为每一个应用程序维护一个消息队例,应用程序的主线程不断地从这个消息 队例中获取消息(Looper),然后对这些消息进行处理(Handler),这样就实现了通过消息来驱动应用程序的执行,本文将详细分析Android 应用程序的消息处理机制. 前面我们学习Android应用程序中的Activ

Android Handler 异步消息处理机制的妙用 创建强大的图片载入类

转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/38476887 ,本文出自[张鸿洋的博客] 近期创建了一个群.方便大家交流,群号:55032675 上一篇博客介绍了Android异步消息处理机制.假设你还不了解,能够看:Android 异步消息处理机制 让你深入理解 Looper.Handler.Message三者关系 . 那篇博客的最后,提出能够把异步消息处理机制不仅仅是在MainActivity中更新UI.能够用到别的地方

Android应用程序消息处理机制笔记

看老罗的Android源码情景分析学习的时候,边抄边理解再总结.希望能为面试提供点帮助吧. 1.Android应用程序是通过消息来驱动,Android应用程序每一个线程在启动时,都可以首先在内部创建一个消息队列.然后再进入到一个无限循环中.不断检查它的消息队列是否有新的消息需要处理,如果有新的消息需要处理,那么线程将会将它从消息队列中取出来,并且对它进行处理,否则,线程就会进入睡眠等待状态,直到有新的消息处理为止.这样就可以通过消息来驱动Android应用程序的执行了. 2.Android应用程