Handler原理

2020-04-23  本文已影响0人  Android刘东

更详细的

1.Handler构造函数

  public Handler() {
        this(null, false);
    }

    public Handler(@Nullable Callback callback) {
        this(callback, false);
    }

  
    public Handler(@NonNull Looper looper) {
        this(looper, null, false);
    }

    public Handler(@NonNull Looper looper, @Nullable Callback callback) {
        this(looper, callback, false);
    }
    
    public Handler(boolean async) {
        this(null, async);
    }

  
    public Handler(@Nullable Callback callback, boolean async) {

        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;
    }

注意:工作线程需要传Looper.Mylooper()否则

if (mLooper == null) {
            throw new RuntimeException(
                "Can't create handler inside thread " + Thread.currentThread()
                        + " that has not called Looper.prepare()");
        }

2.Looper,MessageQueue对象

Looper每个线程只有一个,工作线程可以Looper.myLooper()传参
主线程的Looper是由ActivityThread.java中main函数创建代码如下:

public static void main(String[] args) {
    //省去部分代码
Looper.prepareMainLooper();//创建对象
    Looper.loop();//开始轮询
}
///Looper类
    public static void prepareMainLooper() {
        prepare(false);
        synchronized (Looper.class) {
            if (sMainLooper != null) {
                throw new IllegalStateException("The main Looper has already been prepared.");
            }
            sMainLooper = myLooper();
        }
    }
    private static void prepare(boolean quitAllowed) {
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
    //创建Looper对象
        sThreadLocal.set(new Looper(quitAllowed));
    }
    private Looper(boolean quitAllowed) {
    //创建MessageQueued对象
        mQueue = new MessageQueue(quitAllowed);
        mThread = Thread.currentThread();
    }


3.Handler.SendMessage()方法

//省去部分代码
 public final boolean sendMessage(@NonNull Message msg) {
        return sendMessageDelayed(msg, 0);
    }
 public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) {
        return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
    }
  public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis) {
        MessageQueue queue = mQueue;
        return enqueueMessage(queue, msg, uptimeMillis);
    }

4.添加到消息队列

    boolean enqueueMessage(Message msg, long when) {
        synchronized (this) {
                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.next = p; // invariant: p == prev.next
                prev.next = msg;
            }

            // We can assume mPtr != 0 because mQuitting is false.
            if (needWake) {
                nativeWake(mPtr);
            }
        }
        return true;
    }

5.Loop无限循环

    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相当于Handler.dispatchMessage(msg);
            msg.target.dispatchMessage(msg);
        }


5.Handler.dispatchMessage方法

    public void dispatchMessage(@NonNull Message msg) {
        if (msg.callback != null) {
        //如Handler构造函数为:
        //new Handler(
             //   new Handler.Callback() {
              //      @Override
                 //   public boolean handleMessage(@NonNull Message msg) {
               //     
               //     }
             //   }
       // );
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);//回调
        }
    }

6.Handler中sendMessage和Post区别

 public final boolean post(@NonNull Runnable r) {
       return  sendMessageDelayed(getPostMessage(r), 0);
    }

多了一层getPostMessage(r)。

    private static Message getPostMessage(Runnable r) {
        Message m = Message.obtain();
        m.callback = r;
        return m;
    }

1.post方法:回调在run方法2.sendMessage回调在Handler.handleMessage()或者Handler的callback中

7.Message构造建议

Message mMessage =Message.obtain();

而不是,因为Message.obtain()复用了

Message mMessage =new Message();

8.Looper无线循环为什么不ANR

1.ActivityThread的main方法主要就是做消息循环,一旦退出消息循环,那么你的应用也就退出了.
2.造成ANR的原因一般有两种:
1)当前的事件没有机会得到处理(即主线程正在处理前一个事件,没有及时的完成或者 looper被某种原因阻塞住了)
2)当前的事件正在处理,但没有及时完成
3.Looer.loop()方法可能会引起主线程的阻塞,但只要它的消息循环没有被阻塞,能一直处理事件就不会产生ANR异常。

参考:https://www.jianshu.com/p/b4d745c7ff7a

上一篇下一篇

猜你喜欢

热点阅读