Handler,Lopper,Message,MessageQueue关系

来源:互联网 发布:淘宝网打不开 编辑:程序博客网 时间:2024/06/15 12:04

想了解他们的之间的关系,我们来分析一下系统Handler是如何工作的。
一、首先在ActivityThread.java中有一个main()方法,这是整个App的入口。

  • ActivityThread 的初始化。
    ActivityThread thread = new ActivityThread();
    //里面饿加载一个系统H(Handler)
    //敲黑板。划重点:四大组件等组件的启动和这个Handler密切相关。
    //这里注意一点,就是为什么异常的时候Activity的生命周期不会被调用,很有可以就是这个Handler或者Looper已经挂了,肯定不会执行生命周期的其他方法。
    thread.attach(false);//建立Binder通道 (创建新线程)
  • Lopper:消息循环器
    Looper.prepareMainLooper();//和当前线程进行关联,初始化一个消息队列。
    Looper.loop(); //开始进行循环

二:Handle简单分析

  • 构造函数
    Hanler的构造函数主要是两参和三参构造函数。
/**  * @param callback 回调,在下面会讲到  * @param async 执行过程是否异步操作。默认是true  */public Handler(Callback callback, boolean async) {  ......  //获取当前线程的looper对象  mLooper = Looper.myLooper();  //在主线程是不需要创建Looper对象的,其他线程如果没有创建,需要调用Looper.prepare()创建  if (mLooper == null) {      throw new RuntimeException(          "Can't create handler inside thread that has not called Looper.prepare()");  }  //Handler和MessageQueue的关联是依靠Looper  mQueue = mLooper.mQueue;  mCallback = callback;  mAsynchronous = async;}/**  * @param looper looper循环器  * @param callback 回调,在下面会讲到  * @param async 执行过程是否异步操作。默认是true  */public Handler(Looper looper, Callback callback, boolean async) {  mLooper = looper;  mQueue = looper.mQueue;  mCallback = callback;  mAsynchronous = async;}
  • 发消息:
    sendEmptyMessage(int what);
    sendEmptyMessageDelayed(int what, long delayMillis);
    sendEmptyMessageAtTime(int what, long uptimeMillis);
    发空消息其实也是相当于在池中找了一个Message或者new了一个Message
    Message msg = Message.obtain();
    msg.what = what;
    sendMessageDelayed(msg, delayMillis);

  • 处理消息:

    分发消息

  public void dispatchMessage(Message msg) {//msg.callback是Runable.        if (msg.callback != null) {            //代码块1,调用Runable里的run方法,常用于循环调用,请注意所在线程。            handleCallback(msg);        } else {            //在判断自己有没有回调。有回调就用自己的。            if (mCallback != null) {                if (mCallback.handleMessage(msg)) {                    return;                }            }            //如果都没有,那么直接回调这个方法处理            handleMessage(msg);        }    }
    //代码块,简单举例。    private Handler mHandler = new Handler(){        @Override        public void handleMessage(Message msg) {        }    };    private Runnable mRunnable = new Runnable() {        @Override        public void run() {            mHandler.postDelayed(mRunnable,1000);        }    };   private void handlerRun(){        mHandler.post(mRunnable);    }    private void handlerRemove(){        mHandler.removeCallbacks(mRunnable);    }

三 Looper简单分析:

  • 看一下构造函数
    private Looper(boolean quitAllowed) {        //创建一个looper管理的消息队列 messageQueue。        //相当于给Looper消息循环器绑定一个MessageQueue        mQueue = new MessageQueue(quitAllowed);        //获得当前的线程        mThread = Thread.currentThread();    }
  • 给Looper消息循环器绑定一个MessageQueue。Looper不断的从MessageQueue拿消息给主线程处理。这样的好处是当需要处理新的事件,只需要把消息放入MessageQueue中。
  • ThreadLocal sThreadLocal = new ThreadLocal();线程安全作用,。起到桥梁的作用,把单独的Thread和Thread需要访问的Looper保存一份独立的副本ThreadLocal里面的ThreadLocalMap相当于hashMap,已当前线程为key,保存一个Looper。
  • prepareMainLooper(),prepare()基本一样,前者是拿当前线程设置为主线程。prepare(boolean quitAllowed)只能调用一次,为了保证一个线程只有一个Looper存在。
  • loop(),从MessageQueue中不断的拿数据,并进行分发msg.target.dispatchMessage(msg);最后会回收消息 msg.recycleUnchecked();

  • 来说说Looper.loop();死循环为什么不会卡死,其实当没有任务的时候系统是休眠了,主线程被阻塞在一个无限循环里了。looper维护了一个消息队列,如果队列里有消息就取出来执行,没有就休眠等待消息过来唤醒,
    如果说出现过ANR之类的操作,也不是loop循环导致的,而是循环里的消息处理被阻塞。简单来收,当你一直循环在写各个科目的作业,如果作业写完了,你就可以睡觉,而在你写作业的过程中,你可以去吃饭,上厕所等其他操作。

四:MessageQueue。

  • 在next()时。并不是在队头拿也就是不是依次拿,而是要进行比较:比较when时间,取合适的消息。
  • 消息的回收:当handler把消息处理完成后。在looper的loop方法最后会对消息进行回收。

五:Message:

  • 序列化的。
  • 内部是一个消息池(链表队列)
//从池子里面拿,复用无用的。 //这样节省内存。而不是new Message();Message message = Message().obtain(); message .getTarget().sendEmptyMessage();

六:Handler和Looper关联

  • 在Handler的构造函数中Looper.myLooper()获取当前线程所在的Looper。
  • 如果在子线程中使用handler,需要先调用looper.prepare();,不然mLooper 是null,报异常。
public Handler(Callback callback, boolean async) {        ........        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;    }

最后总结、Handler,Looper,MessageQueue关系:

  1. handler负责发送Message或者Runable,Looper负责接收Handler发送的消息并放入MessageQueue,然后再把消息从MessageQueue取出回传到Handler。
  2. 一个Handler对应一个Looper,一个Looper对应一个MessageQueue,一个Handler可以产生多个Message。
  3. Handler相当于给外部线程的接口,用于线程间通信。Looper是由 系统支持的用于创建和管理MessageQueue的 依附于一个线程的循环对象,而Handler是用于操作线程內部的消息队列,所以Handler也必须依附一个线程。
0 0
原创粉丝点击