Android消息机制

android消息机制的核心类:

  • Looper
  • Handler
  • MessageQueue---单链表
  • Message
  • ThreadLocal

Handler异步通信机制工作流程图

Handler.Looper.MessageQueue关系图:

这里写图片描述

Handler核心类:

  • Handler:

    • Looper(当前线程ThraedLocal)
    • MessageQueue(即为Looper关联的MessageQueue)
    • Imessenger(实现进程之间的通讯)
  • handler发送消息:

    • send方案发送消息(最终将消息放入消息队列中,即queue.enqueue()):
        private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {        msg.target = this;        if (mAsynchronous) {            msg.setAsynchronous(true);        }        return queue.enqueueMessage(msg, uptimeMillis);    }
    • post方法发送消息:(将runnable()封装成Message后,放入队列中)
         private static Message getPostMessage(Runnable r) {        Message m = Message.obtain();        m.callback = r;        return m;    }
  • handler处理消息:

这里写图片描述
    public void dispatchMessage(Message msg) {            if (msg.callback != null) {                handleCallback(msg);            } else {                if (mCallback != null) {                    if (mCallback.handleMessage(msg)) {                        return;                    }                }                handleMessage(msg);            }        }

Looper核心类:

Looper关联MessageQueue,每个Looper对象中都有一个MessageQueue用于存储消息, 关联一个ThreadLocal用于存储当前线程的Looper对象.

  • looper.prepare()
        private static void prepare(boolean quitAllowed) {            if (sThreadLocal.get() != null) {                throw new RuntimeException("Only one Looper may be created per thread");            }            //将looper存储于ThreadLocal中            sThreadLocal.set(new Looper(quitAllowed));        }
  • looper.loop()
        //核心就不断从队列中取出消息,并处理消息, 如果队列中没有消息looper出现阻塞.        public static void loop() {            //.....            for (;;) {                Message msg = queue.next(); // might block                if (msg == null) {                    // No message indicates that the message queue is quitting.                    return;                }                //.....                msg.target.dispatchMessage(msg);                //.....                msg.recycleUnchecked();            }        }
  • 将线程变为looper线程, 类似于HandlerThread:
        public class LooperThread extends Thread {            @Override            public void run() {                // 将当前线程初始化为Looper线程                Looper.prepare();                        // ...其他处理,如实例化handler                        // 开始循环处理消息队列                Looper.loop();            }        }

MessageQueue:

MessageQueue内部并不是队列,而是通过单链表结构来维护消息列表,单链表在插入和删除上比较有优势.

  • 插入功能(enqueueMessage())

  • 取出功能(next())即链表的删除功能)

主线程的消息循环:

Android的主线程就是ActivityThread,入口方法main();通常在新打开一个APK界面时,ActivityManagerService会为该APK启动一个新的新建ActivityThread作为该APK的主线程。该主线程的main函数主要做了两件事:

  • 新建ActivityThread对象。
  • 使用主线程进入消息循环。
    public final class ActivityThread {             ...                    public static void main(String[] args) {                    ...            Looper.prepareMainLooper();                        ActivityThread thread = new ActivityThread();            thread.attach(false);                  ...            Looper.loop();                                ...        }    }
  • 主线程消息循环后,需要一个Handler和消息队列交互:
        public final class ActivityThread {                ...                    final H mH = new H();                    ...                    private class H extends Handler {                ...                         public void handleMessage(Message msg) {                    ...                            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;                                ...                    }                }            }        }
  • ActivityThread通过ApplicationThread和AMS进行进程间通讯,AMS以进程间通讯的方法完成ActivityThread的请求后回调ApplicationThread中的Binder方法,然后ApplicationThread会向H发送消息,H收到消息后会将ApplicationThread逻辑切换到ActivityThread中执行,即切换到主线程中执行.
        public final class ActivityThread {            ...                    private class ApplicationThread extends ApplicationThreadNative {                ...                        public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,                        ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,                        int procState, Bundle state, List pendingResults,                        List pendingNewIntents, boolean notResumed, boolean isForward,                        String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler) {                            ...                            sendMessage(H.LAUNCH_ACTIVITY, r);                }                        ...            }                    ...                    private void sendMessage(int what, Object obj) {                sendMessage(what, obj, 0, 0, false);            }                    private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {                        Message msg = Message.obtain();                msg.what = what;                msg.obj = obj;                msg.arg1 = arg1;                msg.arg2 = arg2;                if (async) {                    msg.setAsynchronous(true);                }                mH.sendMessage(msg);            }                    ...        }

Handler内存泄露:

This Handler class should be static or leaks might occur 。

  • 确保class内部的handler不含有外部类的隐式引用 。 同一个线程下的handler共享一个looper对象,消息中保留了对handler的引用,只要有消息在队列中,那么handler便无法被回收,如果handler不是static那么使用Handler的Service和Activity就也无法被回收。这就可能导致内存泄露。
  • 官方推荐将handler设为static类,并在里面使用弱引用WeakReference
public static class ServiceHandler extends Handler {        WeakReference activityRef;        public ServiceHandler(WeakReference activityRef) {            this.activityRef = activityRef;        }        @Override        public void handleMessage(Message msg) {            Device device = null;            switch (msg.what) {                case Constant.MSG_NOTIFY_SERVER_CONNECT: //连上服务器//                    Toast.makeText(activityRef.get(), "Have connected the socket server!", Toast.LENGTH_SHORT).show();                    break;                case Constant.MSG_NOTIFY_SERVER_DISCONNECT: //与服务器断开//                    Toast.makeText(activityRef.get(), "Have disconnected the socket server!", Toast.LENGTH_SHORT).show();                    break;                case Command.SMS_REPLY_COMMAND: //GSM回复                case Constant.MSG_NOTIFY_DEVICE_REPLY: //GPRS回复                    activityRef.get().mHandler.removeMessages(Command.TIME_OUT_CMD);                    activityRef.get().performNextActionWithCorrespondingCommand((String) msg.obj);                    break;                case Constant.MSG_NOTIFY_DEVICE_ONLINE_STATUS:                    device = (Device) msg.obj;                    activityRef.get().notifyDeviceOnlineStatus(device);                    break;    }}

更多相关文章

  1. Android的Handler机制详解3_Looper.looper()不会卡死主线程
  2. Android之Handler用法总结
  3. Android开发之消息处理机制(一)——Handler
  4. Android异步加载图像小结 (含线程池,缓存方法)
  5. android 面试题集
  6. Titanium 使用刘明星的Jpush module做android端的消息推送
  7. android 电容屏(二):驱动调试之基本概念篇
  8. [Innost]Android深入浅出之Binder机制
  9. Android(安卓)常用组价申明及使用简集

随机推荐

  1. Android 单击图片切换效果
  2. Android(安卓)源代码结构
  3. 如何为一个组件的同一属性同时声明两个值
  4. Android2.2添加busybox 支持——基于Andr
  5. 基于Android DataBinding的InverseBindin
  6. Android中系统自带数据库文件中的多表联
  7. Android]仿通讯录ListView小例子
  8. android 开源 OCR 项目 及手写识别
  9. Android(安卓)- fill_parent、wrap_conte
  10. Android之一个简单计算器源代码