关于这几个技术术语,让我们从Android的实际使用中来渐渐理清它们。

1. Looper的初始化

Application被创建时,ActivityThread的main函数会被调用,其中初始化了一个Looper

Looper.prepareMainLooper();

其实现在Looper.java中:

    /**     * Initialize the current thread as a looper, marking it as an     * application's main looper. The main looper for your application     * is created by the Android environment, so you should never need     * to call this function yourself.  See also: {@link #prepare()}     */    public static void prepareMainLooper() {        prepare(false); //进行初始化        synchronized (Looper.class) {            if (sMainLooper != null) {                throw new IllegalStateException("The main Looper has already been prepared.");            }            sMainLooper = myLooper(); //赋值        }    }

prepare(false)是对Looper进行初始化, 初始化之后调用将Looper对象赋值给sMainLooper. 所以我们只需要看prepare函数:

    ......    static final ThreadLocal sThreadLocal = new ThreadLocal();    ......    private static void prepare(boolean quitAllowed) {        if(sThreadLocal.get() != null) {            throw new RuntimeException("Only one Looper may be created per thread");        } else {            sThreadLocal.set(new Looper(quitAllowed)); //创建一个Looper对象,放入ThreadLocal中        }    }

从之前的描述可以看出,Looper是一个单例,所以其构造函数是private的:

    private Looper(boolean quitAllowed) {        this.mQueue = new MessageQueue(quitAllowed);        this.mRun = true;        this.mThread = Thread.currentThread();    }

2. 初始化MessageQueue

上面的Looper的构造函数中又初始化了一个MessageQueue,这里又引出了一个重要的对象MessageQueue . 每个Looper都保持一个MessageQueue用来存放Message. 这里只需要记住Looper和MessageQueue的关系即可.下面是MessageQueue 的构造函数:

/** * Low-level class holding the list of messages to be dispatched by a * Looper.  Messages are not added directly to a MessageQueue, * but rather through  Handler objects associated with the Looper. *  * You can retrieve the MessageQueue for the current thread with *  Looper.myQueue(). */    MessageQueue(boolean quitAllowed) {        mQuitAllowed = quitAllowed;        mPtr = nativeInit();    }

从构造函数上面的描述可以看到,Message是不能直接加入到MessageQueue中的, 必须通过Handler来添加. 这里你可能会有疑问,为什么Message不能直接加入到MessageQueue里面呢?带着这个问题我们继续向下看。

3. 创建ActivityThread对象

Looper初始化完成后, 回到ActivityThread的main函数, 这里还创建了一个ActivityThread对象,对App来说,ActivityThread是一个非常重要的类,

        //初始化ActivityThread        ActivityThread thread = new ActivityThread();        thread.attach(false);        if (sMainThreadHandler == null) {            sMainThreadHandler = thread.getHandler();        }

ActivityThread的构造函数中初始化了ResourcesManager,保存在mResourcesManager中. thread.attach(false)这个比较重要,是进行一些状态的设置和初始化. 随后会初始化这个应用程序UI线程的Handle .下面是getHandler()

    final Handler getHandler() {        return mH;    }

其中mH的定义如下:

private class H extends Handler {        public void handleMessage(Message msg) {            if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));            switch (msg.what) {                case LAUNCH_ACTIVITY: {                    final ActivityClientRecord r = (ActivityClientRecord) msg.obj;                    r.packageInfo = getPackageInfoNoCheck(                            r.activityInfo.applicationInfo, r.compatInfo);                    handleLaunchActivity(r, null);                } break;                case RELAUNCH_ACTIVITY: {                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityRestart");                    ActivityClientRecord r = (ActivityClientRecord)msg.obj;                    handleRelaunchActivity(r);                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);        }}

其handleMessage这个函数很长,仔细看就可以发现,这里调度了应用开发中各个组件的生命周期.包括activityRestart/activityPause/activityStop/activityDestroy/activityNewIntent等等.

4. 执行消息循环

随后main函数会调用Looper.loop(),其定义如下:

    /**     * Run the message queue in this thread. Be sure to call     * {@link #quit()} to end the loop.     */    public static void loop() {        final Looper me = myLooper();        ......        final MessageQueue queue = me.mQueue;        ......        for (;;) {            Message msg = queue.next(); // might block            .......            msg.target.dispatchMessage(msg);            ......            msg.recycleUnchecked();        }    }

可以看到其中调用了一个死循环for (;;),在循环开始调用

Message msg = queue.next(); // might block

来从MessageQueue中获取Message来进行处理.注意到MessageQueue的next函数会调用this.nativePollOnce(this.mPtr, nextPollTimeoutMillis); 这是一个阻塞方法. 会调用到Native层的Looper的一些方法. 当有消息的时候,就会返回一个Message.

这时候一个Activity的Handle/ Looper / MessageQueue都已经跑起来了.他们直接的关系也清楚了.

5. 自己创建的Handler与Looper和MessageQueue之间的关系

在Android开发中,我们一般会自己创建一个Handler,然后发送Message进行通信 (典型场景就是创建一个子线程, 在其中执行耗时较多的操作,然后发一个Message通知UI更新)

第一种写法:无参数的Handler

    Handler defaultHandler = new Handler() {        @Override        public void handleMessage(Message msg) {            switch (msg.what) {                case MSG_HELLO:                    Log.w(TAG, "defaultHandler ThreadName = "                            + defaultHandler.getLooper().getThread().getName());            }        }    };......//使用        new Thread(){            @Override            public void run() {                defaultHandler.sendEmptyMessage(MSG_HELLO);            }        }.start();

其打印结果如下:

Thread Name

这种写法创建的Handler,将自动与当前运行的线程相关联,也就是说这个自定义的Handler将与当前运行的线程使用同一个消息队列,并且可以处理该队列中的消息.如果不太理解这个可以查看Handler的构造函数:

    public Handler(Callback callback, boolean async) {        ......        mLooper = Looper.myLooper();        ......        mQueue = mLooper.mQueue;        mCallback = callback;        mAsynchronous = async;    }

可以看到, Handler中的mLooper和mQueue就是之前ActivityThread中初始化好的.由于Looper是单例,也就是说mLooper和mQueue都只有一个, 而Handler的sendMessage最终会调用sendMessageAtTime:

    public boolean sendMessageAtTime(Message msg, long uptimeMillis) {        MessageQueue queue = mQueue;        ......        return enqueueMessage(queue, msg, uptimeMillis);    }

看到这里,应该对自己创建的Handler和MessageQueue以及Looper直接的关系更清楚了.

第二种写法:参数包含Looper的Handler

Handler有好几个构造函数,其中如果参数中不包含Looper,则最终会进入第一种写法中的那个构造函数,如果参数中包含Looper,则会进入到三个参数的构造函数中:

    /**     * Use the provided Looper instead of the default one and take a callback     * interface in which to handle messages.  Also set whether the handler     * should be asynchronous.     *     * Handlers are synchronous by default unless this constructor is used to make     * one that is strictly asynchronous.     *     * Asynchronous messages represent interrupts or events that do not require global ordering     * with represent to synchronous messages.  Asynchronous messages are not subject to     * the synchronization barriers introduced by MessageQueue#enqueueSyncBarrier(long).     *     * @param looper The looper, must not be null.     * @param callback The callback interface in which to handle messages, or null.     * @param async If true, the handler calls  Message#setAsynchronous(boolean) for     * each Message that is sent to it or Runnable that is posted to it.     *     * @hide     */    public Handler(Looper looper, Callback callback, boolean async) {        mLooper = looper;        mQueue = looper.mQueue;        mCallback = callback;        mAsynchronous = async;    }

这种Handler初始化的时候必须创建一个Looper对象

    Handler mHandler;    class CustomThread extends Thread {        @Override        public void run() {            Looper.prepare();            mHandler = new Handler() {                @Override                public void handleMessage(Message msg) {                    switch (msg.what) {                        case MSG_HELLO:                            Log.w(TAG, "defaultHandler ThreadName = "                            + defaultHandler.getLooper().getThread().getName());                            break;                        default:                            break;                    }                }            };            Looper.loop();        }    }//使用        CustomThread mCustomThread = new CustomThread();        mCustomThread.start();

我给TextView加了一个点击事件,点击会打印对应的线程名:

        appNameText.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                mHandler.sendEmptyMessage(MSG_HELLO);                Log.w(TAG, "MainThreadName =" + getMainLooper().getThread().getName());            }        });

其结果如下:

Different Thread

通过上面两个例子,你应该对Thread/Looper/MessageQueue/Handler有更深入的了解了.

更多相关文章

  1. Android(安卓)Java笔试题(带大部分答案)
  2. Android(安卓)SDK开发 -- TitleBar重构 (代理模式-优化)
  3. 如何监听Phone的状态,第三方App如何拨打/接听电话?
  4. android调用matlab中的函数方法
  5. Volley的基本使用
  6. Android(安卓)exfat移植指南
  7. Android(安卓)移动开发TIPS小结4
  8. Android媒体扫描代码分析
  9. 阿里巴巴Android(安卓)技术规范文档知识点(个人认为有用的)

随机推荐

  1. Android拍照、相册 获取图片后,裁剪图片
  2. android如何静默方式来安装apk
  3. Android获取点击屏幕的位置坐标
  4. Android(安卓)中替换开机动画(附动画包)
  5. 解决 Android(安卓)下载中文文件名问题
  6. Android(安卓)Studio导入Android系统源码
  7. Android的Handler总结
  8. Eclipse中怎样安装Andriod ADT的插件
  9. Android(安卓)ViewGroup 触摸屏事件派发
  10. 探究Android中浏览器UA的生成策略