Handler

在程序的入口

public static void main(String[] args) {
        ...

        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();

        // ams 和 当前进程 进行一个绑定
        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();

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

程序启动,到结束,main方法就结束了,但是app结束,就退出程序了,所以不能结束,Looper.loop(); 可以看成一个死循环
如果要结束程序,要loop结束,handler接收到消息,就会结束

 case EXIT_APPLICATION:
                    if (mInitialApplication != null) {
                        mInitialApplication.onTerminate();
                    }
                    Looper.myLooper().quit(); // 退出loop

系统Handler
客户端Handler

final H mH = new H(); // 饿汉式加载,直接初始化

handleMessage 方法中接收系统的消息,4大组件生命周期,都是通过发消息Handler来处理

我们来看Looper.loop();

public static void loop() {
        // 获取  消息泵
        final Looper me = myLooper();
       // 消息泵中有一个消息队列
        final MessageQueue queue = me.mQueue;

        ...
        // 进行死循环
        for (;;) {
            Message msg = queue.next(); // 注释1
            // 如果没有消息,则继续循环
            if (msg == null) {
                // No message indicates that the message queue is quitting.
                return;
            }

            ...
            // 获取到消息,并进行派发target 就是handler  注释2
            try {
                msg.target.dispatchMessage(msg);
                if (observer != null) {
                    observer.messageDispatched(token, msg);
                }
                dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
            } catch (Exception exception) {
                if (observer != null) {
                    observer.dispatchingThrewException(token, msg, exception);
                }
                throw exception;
            } finally {
                ThreadLocalWorkSource.restore(origWorkSource);
                if (traceTag != 0) {
                    Trace.traceEnd(traceTag);
                }
            }
            ...
            // 进行消息的回收处理
            msg.recycleUnchecked();
        }
    }

我们看looper 就一只在循环,当在队列中没有消息继续循环,有了消息,看到注释1 处,进行获取消息,注释2处,进行派发消息
获取消息,并不是队列的先进先出,因为消息带有时间,根据时间判断,如果当前时间小于消息时间,就先不发送,大于当前时间,则按队列顺序发送

# 进行获取消息,是在MessageQueue.java

@UnsupportedAppUsage
    Message next() {
        ...
        //  也是个死循环,因为消息有时间,没到就等到时间
        for (;;) {
            if (nextPollTimeoutMillis != 0) {
                Binder.flushPendingCommands();
            }

            nativePollOnce(ptr, nextPollTimeoutMillis);

            synchronized (this) {
                ...
                if (msg != null) {
                    // 当前时间 和 消息时间比较
                    if (now < msg.when) {
                        // Next message is not ready.  Set a timeout to wake up when it is ready.
                        nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
                    } else {
                        // Got a message.
                        mBlocked = false;
                        if (prevMsg != null) {
                            prevMsg.next = msg.next;
                        } else {
                            mMessages = msg.next;
                        }
                        msg.next = null;
                        if (DEBUG) Log.v(TAG, "Returning message: " + msg);
                        msg.markInUse();
                        return msg;
                    }
                } else {
                    // No more messages.
                    nextPollTimeoutMillis = -1;
                }
              ...
        }
    }

进行派发消息

# 注释2处,进行派发消息
# Handler
public void dispatchMessage(@NonNull Message msg) {
        // callback 其实就一个 Runnable
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            // 当没有Runnable  则调用自己重写的handleMessage方法,里面是空的
            handleMessage(msg);
        }
    }
// 相当于调用了 Runnable 的run方法,其实还是在当前线程执行
private static void handleCallback(Message message) {
        message.callback.run();
}

# Message
Runnable callback;

上述写法 ,相当于派发了消息,如果有Callback,就执行run,没有就执行 handleMessage

Handler handler = new Handler();
    int i = 0;
    Runnable run = new Runnable() {
        @Override
        public void run() {
            Log.e(TAG, "run: " + i++);
            handler.postDelayed(run, 1000);
            if(i == 10){
                handler.removeCallbacks(run);
            }
        }
    };


 handler.post(run);

handler的发送消息,是可以带时间的,分为马上发,或者延迟发,发送消息的时候,消息是从消息吃中取,当前开始也没有,也是new出来的,当handler执行完消息派发,则在loop方法中调用msg.recycleUnchecked();来进行回收

# message
public static Message obtain() {
        synchronized (sPoolSync) {
            if (sPool != null) {
                Message m = sPool;
                sPool = m.next;
                m.next = null;
                m.flags = 0; // clear in-use flag
                sPoolSize--;
                return m;
            }
        }
        return new Message();
    }

# handler
//uptimeMillis  就是这条消息的时间
public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis) {
        MessageQueue queue = mQueue;
        if (queue == null) {
            RuntimeException e = new RuntimeException(
                    this + " sendMessageAtTime() called with no mQueue");
            Log.w("Looper", e.getMessage(), e);
            return false;
        }
        return enqueueMessage(queue, msg, uptimeMillis);
    }

消息 一种有Runnable 一种是没有

因为是多线程的,每个线程都会访问同一个message,所以会出现问题,就出现了ThreadLocal,里面放的就是Looper

handler 可以这样理解,
要使用handler,就需要进行Looper.prepare();Looper.loop();子线程中使用如下,

class LooperThread extends Thread {
        public Handler mHandler;

        public void run() {
            Looper.prepare();

            mHandler = new Handler() {
                public void handleMessage(Message msg) {
                    // process incoming messages here
                }
            };

            Looper.loop();
        }
    }

主线程之所以不用,是因为主线程中系统已经写了
Looper.prepareMainLooper();之后又有Looper.loop();

handler在系统中存在2中通信,1系统的,Activity的生命周期,2自己写的,为什么自己写的不可以像系统handler发消息呢?
因为handler 是通过ThreadLocal这个类进行封装,里面包含了,loop中又有Thread当前线程,MessageQueue消息队列,handler通过发送消息发送到当前线程的MessageQueue中,又从中取消息,这样就不会发送到系统里面了
handler 容易造成内存泄露,我们可以在handler post的时候弄个Runnable,之后再Activity结束时候,进行handler.removeCallbacks(run);// 移除创建的Runnable

你可能感兴趣的:(Handler)