Handler 源码解读

182 阅读2分钟

首先定义三个个Hander,一个在主线程的Handler,两个个在子线程的Handler

  • 在主线程的Handler定义如下
   Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            if (msg.what == MSG_MAIN) {
                LogUtils.e(TAG, "handler1====" + Thread.currentThread().getName());
            }
            super.handleMessage(msg);
        }
    };

Message message = handler.obtainMessage();
                message.what = MSG_MAIN;
                handler.sendMessage(message);

执行后的日志如下

 handler1====main
  • 在子线程的Handler定义如下
 new Thread(new Runnable() {
                    @Override
                    public void run() {
                        handler2 = new Handler(Looper.getMainLooper()) {
                            @Override
                            public void handleMessage(Message msg) {
                                super.handleMessage(msg);
                                if (msg.what == MSG_THREAD) {
                                    LogUtils.e(TAG, "handler2========" + Thread.currentThread().getName());
                                }
                            }
                        };

                        Message message2 = handler2.obtainMessage();
                        message2.what = MSG_THREAD;
                        handler2.sendMessage(message2);

                    }
                }).start();

执行后日志如下:

 handler2========main
  • 在子线程定义的Handler如下
 new Thread(new Runnable() {
                    @Override
                    public void run() {
                        Looper.prepare();
                        Handler handler3 = new Handler() {
                            @Override
                            public void handleMessage(Message msg) {
                                super.handleMessage(msg);
                                if (msg.what == MSG_THREAD_NEW) {
                                    LogUtils.e(TAG, "handler3========" + Thread.currentThread().getName());
                                }
                            }
                        };
                        handler3.sendEmptyMessage(MSG_THREAD_NEW);
                        Looper.loop();
                    }
                }).start();

执行后日志如下:

handler3========Thread-5

##总结:主线程可以直接使用定义Handler且执行在主线程,如果在子线程定义Handler,并使用Hanlder(Looper.getMainLooper()),则发送的消息也是在主线程执行;如果在子线程定义Handler使用,需要使用Loop.prepare();定义完Handler后,Loop.loop(),则发送的消息在子线程执行

 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();
        if (mLooper == null) {
            throw new RuntimeException(
                "Can't create handler inside thread " + Thread.currentThread()
                        + " that has not called Looper.prepare()");
        }
        mQueue = mLooper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }
  • 创建Handler时,要确定Looper是否为null,如果是null,则报错
 /**
     * Return the Looper object associated with the current thread.  Returns
     * null if the calling thread is not associated with a Looper.
     */
    public static @Nullable Looper myLooper() {
        return sThreadLocal.get();
    }
  • 获取Looper是通过ThreadLocal 变量获取,子线程使用Handler时,Looper.prepare(),是初始化
    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.prepare,因为在ActivityThread的Main方法中,有初始化

 public static void main(String[] args) {
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");

        // CloseGuard defaults to true and can be quite spammy.  We
        // disable it here, but selectively enable it later (via
        // StrictMode) on debug builds, but using DropBox, not logs.
        CloseGuard.setEnabled(false);

        Environment.initForCurrentUser();

        // Set the reporter for event logging in libcore
        EventLogger.setReporter(new EventLoggingReporter());

        // Make sure TrustedCertificateStore looks in the right place for CA certificates
        final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
        TrustedCertificateStore.setDefaultUserDirectory(configDir);

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

        Looper.prepareMainLooper();

        // Find the value for {@link #PROC_START_SEQ_IDENT} if provided on the command line.
        // It will be in the format "seq=114"
        long startSeq = 0;
        if (args != null) {
            for (int i = args.length - 1; i >= 0; --i) {
                if (args[i] != null && args[i].startsWith(PROC_START_SEQ_IDENT)) {
                    startSeq = Long.parseLong(
                            args[i].substring(PROC_START_SEQ_IDENT.length()));
                }
            }
        }
        ActivityThread thread = new ActivityThread();
        thread.attach(false, startSeq);

        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
        }

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

        // End of event ActivityThreadMain.
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        Looper.loop();