美文网首页
Android Handler源码分析

Android Handler源码分析

作者: 天道__ | 来源:发表于2019-04-09 16:37 被阅读0次

    一、源码分析

    1. 一般调用
     mHandler.sendEmptyMessage(100);
    
    2. Handler.java
     public final boolean sendEmptyMessage(int what)
     {
            return sendEmptyMessageDelayed(what, 0);
     }
     
     public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
            Message msg = Message.obtain();
            msg.what = what;
            return sendMessageDelayed(msg, delayMillis);
     }
     
     public final boolean sendMessageDelayed(Message msg, long delayMillis)
      {
            if (delayMillis < 0) {
                delayMillis = 0;
            }
            return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
      }
      
     public boolean sendMessageAtTime(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);
      }
    
     private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
            msg.target = this;
            if (mAsynchronous) {
                msg.setAsynchronous(true);
            }
            return queue.enqueueMessage(msg, uptimeMillis);
      }
    
    
    3. MessageQueue.java
     boolean enqueueMessage(Message msg, long when) {
            if (msg.target == null) {
                throw new IllegalArgumentException("Message must have a target.");
            }
            if (msg.isInUse()) {
                throw new IllegalStateException(msg + " This message is already in use.");
            }
    
            synchronized (this) {
                if (mQuitting) {
                    IllegalStateException e = new IllegalStateException(
                            msg.target + " sending message to a Handler on a dead thread");
                    Log.w(TAG, e.getMessage(), e);
                    msg.recycle();
                    return false;
                }
    
                msg.markInUse();
                msg.when = when;
                Message p = mMessages;
                boolean needWake;
                // 第一次添加数据到队列中,或者当前 msg 的时间小于 mMessages 的时间
                if (p == null || when == 0 || when < p.when) {
                    // New head, wake up the event queue if blocked.
                    msg.next = p;
                    mMessages = msg;
                    needWake = mBlocked;
                } else {
                    // Inserted within the middle of the queue.  Usually we don't have to wake
                    // up the event queue unless there is a barrier at the head of the queue
                    // and the message is the earliest asynchronous message in the queue.
                    needWake = mBlocked && p.target == null && msg.isAsynchronous();
                    Message prev;
                    for (;;) {
                        prev = p;
                        p = p.next;
                        if (p == null || when < p.when) {
                            break;
                        }
                        if (needWake && p.isAsynchronous()) {
                            needWake = false;
                        }
                    }
                    // 把当前 msg 插入到列表中
                    msg.next = p; // invariant: p == prev.next
                    prev.next = msg;
                }
    
                // We can assume mPtr != 0 because mQuitting is false.
                if (needWake) {
                    nativeWake(mPtr);
                }
            }
            return true;
      }
    
    4.把消息都存到队列里面去了,然后他们是怎么轮训的呢?(Looper.java)
      /**
       * 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();
            if (me == null) {
                throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
            }
            final MessageQueue queue = me.mQueue;
    
            // Make sure the identity of this thread is that of the local process,
            // and keep track of what that identity token actually is.
            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);
                }
                // 通过 target 去 dispatchMessage 而 target 就是绑定的 Handler
                msg.target.dispatchMessage(msg);
    
                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.recycleUnchecked();
            }
        }
    
    5. 这个loop是什么时候调用的呢?我们看看ActivityThread的main方法(ActivityThread.java)
    public static void main(String[] args) {
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
            SamplingProfilerIntegration.start();
    
            Process.setArgV0("<pre-initialized>");
            // 初始化Looper
            Looper.prepareMainLooper();
    
            ActivityThread thread = new ActivityThread();
            thread.attach(false);
    
            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();
    
           
        }
    
    
    6. 总结
    • handler.sendMessage 其实只是把我们的 Message 加入了消息队列,队列采用的是链表的方式,按照 when 也就是时间排序,然后再也没干其他;
    • Looper的loop一直轮训这个队列,这是一个死循环,然后调用message的target,就是我们写的Handler执行dispatchMessage。
    • 当Laucher启动一个App的时候,首先会通过zygote Fork一个进程,然后进程会执行ActivityThread的main函数,在main函数里面初始化looper,执行loop。

    二、自己手写

    1. Handler
    public class Handler {
        // 包含一个消息队列
        MessageQueue mQueue;
        
        public Handler() {
        //获取looper 轮训器。在Activity启动的时候创建
            Looper looper = Looper.myLooper();
            
            if(looper == null){
                throw new RuntimeException(
                        "Can't create handler inside thread that has not called Looper.prepare()");
            }
            
            mQueue= looper.mQueue;
        }
        
        public void sendMessage(Message message) {
            sendMessageDelayed(message,0);
        }
        
        public final boolean sendMessageDelayed(Message msg, long delayMillis)
        {
            if (delayMillis < 0) {
                delayMillis = 0;
            }
            return sendMessageAtTime(msg, System.currentTimeMillis() + delayMillis);
        }
        
        public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
            MessageQueue queue = mQueue;
            return enqueueMessage(queue, msg, uptimeMillis);
        }
        
        private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
            msg.target = this;
            return queue.enqueueMessage(msg, uptimeMillis);
        }
        
        // 空方法并没具体的实现
        public void handleMessage(Message msg) {
            
        }
    }
    
    2. Looper
    public class Looper {
        // sThreadLocal.get() will return null unless you've called prepare().
        static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
        
        public static void prepare() {
            sThreadLocal.set(new Looper());
        }
    
        MessageQueue mQueue;
        
        public Looper() {
            mQueue = new MessageQueue();
        }
    
        public static void loop() {
        //无限轮训 获取队列里面的消息
            Looper looper = myLooper();
            for(;;){
                MessageQueue queue = looper.mQueue;
                
                Message message = queue.next();
                
                if(message == null){
                    return;
                }
                
                message.target.handleMessage(message);
            }
        }
    
        static Looper myLooper() {
            return sThreadLocal.get();
        }
    
    }
    
    3. MessageQueue
    public class MessageQueue {
        private Message mMessages;
    
        // 按照时间排序插入
        public boolean enqueueMessage(Message msg, long when) {
            synchronized (this) {
                msg.when = when;
                Message p = mMessages;
                //按照when 的时间进行排序插入
                if (p == null || when == 0 || when < p.when) {
                    // New head, wake up the event queue if blocked.
                    msg.next = p;
                    mMessages = msg;
                } else {
                    Message prev;
                    for (;;) {
                        prev = p;
                        p = p.next;
                        if (p == null || when < p.when) {
                            break;
                        }
                    }
                    msg.next = p; // invariant: p == prev.next
                    prev.next = msg;
                }
            }
            return true;
        }
    
       // 无限轮训 获取下一个消息
        public Message next() {
            int pendingIdleHandlerCount = -1; // -1 only during first iteration
            for (;;) {
    
                synchronized (this) {
                    // Try to retrieve the next message. Return if found.
                    final long now = System.currentTimeMillis();
                    Message prevMsg = null;
                    Message msg = mMessages;
                    if (msg != null && msg.target == null) {
                        // Stalled by a barrier. Find the next asynchronous message
                        // in the queue.
                        do {
                            prevMsg = msg;
                            msg = msg.next;
                        } while (msg != null);
                    }
                    if (msg != null) {
                        if (now < msg.when) {
                            // Next message is not ready. Set a timeout to wake up
                            // when it is ready.
                        } else {
                            if (prevMsg != null) {
                                prevMsg.next = msg.next;
                            } else {
                                mMessages = msg.next;
                            }
                            msg.next = null;
                            return msg;
                        }
                    } else {
                    }
    
                    if (pendingIdleHandlerCount <= 0) {
                        continue;
                    }
                }
            }
        }
    }
    
    
    4. Message
    public class Message {
    
        public Object obj;
        public Handler target;
        public long when;
        public Message next;
    
    }
    
    5. 因为Looper是在主线程中执行的,我们来写一个ActivityThread
    public class ActivityThread {
        final H mH = new H();
        
        public void attach(boolean b) {
            Activity mainActivity = new TestActivity();
            mainActivity.onCreate();
    
            // 通过 Handler 去执行Activity的生命周期
            Message message = new Message();
            message.obj = mainActivity;
            mH.sendMessage(message);
        }
    
        private class H extends Handler {
            public void handleMessage(Message msg) {
                Activity mainActivity = (Activity) msg.obj;
                mainActivity.onResume();
            }
        }
    }
    
    6. 模拟Activity
    public class Activity {
    
        public void onCreate(){
            
        }
        
        public void onResume(){
            
        }
        
        public TextView findViewById(int id){
            return new TextView();
        }
    }
    
    7. TestActivity
    /**
     * @author 512573717@qq.com
     * @created 2018/8/23  下午7:08.
     */
    public class TestActivity extends Activity {
        private static final String TAG = "TestActivity";
        private TextView mHTextView;
    
        private Handler mHHandler = new Handler() {
    
            @Override
            public void handleMessage(Message message) {
                Log.e(TAG, "当前线程名称===="+Thread.currentThread().getName());
                mHTextView.setText((CharSequence) message.obj);
            }
        };
    
        @Override
        public void onCreate() {
            super.onCreate();
    
            Log.e(TAG, "onCreate");
            mHTextView = findViewById(0x111111);
            new Thread(new Runnable() {
                @Override
                public void run() {
    
    //                mHTextView.setText("I  will be  update !!!");
    
                    Log.e(TAG, "当前线程名称==="+Thread.currentThread().getName());
    
                    try {
                        Thread.sleep(100);
                        Message msg = new Message();
                        msg.obj = "I  will be  update !!!";
                        mHHandler.sendMessage(msg);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
    
                }
            }
            ).start();
    
        }
    
        @Override
        public void onResume() {
            super.onResume();
            Log.e(TAG, "onResume");
        }
    }
    
    8. 模拟UI控件TextView
    public class TextView {
        private Thread mThread;
        public TextView(){
            mThread = Thread.currentThread();
        }
        
        public void setText(CharSequence text){
            checkThread();
    
            System.out.println("更新UI成功:"+text);
        }
        
        void checkThread() {
            if (mThread != Thread.currentThread()) {
                throw new RuntimeException(
                        "Only the original thread that created a view hierarchy can touch its views.");
            }
        }
    }
    
    9. Client
    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            Looper.prepare();
    
            ActivityThread thread = new ActivityThread();
            thread.attach(false);
    
            Looper.loop();
        }
    
    }
    
    10 .打印结果
     1945-1945/? E/TestActivity: onCreate
     1945-1945/? E/TestActivity: onResume
     1945-1957/? E/TestActivity: 当前线程名称===Thread-161
     1945-1945/demo.dhcc.com.handlerdemo E/TestActivity: 当前线程名称====main
     1945-1945/demo.dhcc.com.handlerdemo I/System.out: 更新UI成功:I  will be  update !!!
    

    三、面试相关问题

    1. 为什么不能再子线程里面创建Handler
     new Thread(new Runnable() {
                @Override
                public void run() {
    
                    Handler  handler=new Handler();
                    handler.sendMessage(Message.obtain());
                }
            }).start();
            
     //
    

      这个时候会报错“Can't create handler inside thread that has not called Looper.prepare()”,查看源码发现。

       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 that has not called Looper.prepare()");
            }
            mQueue = mLooper.mQueue;
            mCallback = callback;
            mAsynchronous = async;
        }
    

      修改代码

        Looper.prepare();
        Handler  handler=new Handler();
        handler.sendMessage(Message.obtain());
        Looper.loop();
    

      为什么这样有可以

       public static void prepare() {
            prepare(true);
        }
    
        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));
        }
        
        public void set(T value) {
            Thread t = Thread.currentThread();
            ThreadLocalMap map = getMap(t);
            if (map != null)
                map.set(this, value);
            else
                createMap(t, value);
        }
    
    

      为什么主线程的可以(ActivityThread.java)

    public static void main(String[] args) {
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
            SamplingProfilerIntegration.start();
    
        
            Process.setArgV0("<pre-initialized>");
    
           // 启动时已经创建了
            Looper.prepareMainLooper();
    
            ActivityThread thread = new ActivityThread();
            thread.attach(false);
    
            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();
            
        }
    
    总结

       一个Looper对应一个线程。存放在ThreadLocal里面。Looper必须创建了才有消息队列。如果没有消息队列Message就没地方存。所以必须先创建Looper。

    相关文章

      网友评论

          本文标题:Android Handler源码分析

          本文链接:https://www.haomeiwen.com/subject/qmliiqtx.html