• 【读书笔记】Android Handler和Looper流程


    最近在阅读《Android系统源代码情景分析》,记录一下Android Handler和Looper流程。

    Looper由ActivityThread.main()创建并启动消息循环,ActivityThread.main()代码如下:

    public static void main(String[] args) {
    
            ...
    
            //创建Lopper
            Looper.prepareMainLooper();
    
            ActivityThread thread = new ActivityThread();
            thread.attach(false);
    
            if (sMainThreadHandler == null) {
                sMainThreadHandler = thread.getHandler();
            }
    
            //为AsyncTask指定MainLooper,使得AsyncTask的回调函数运行在主线程上
            //此代码在5.1之后被移除
            AsyncTask.init();
    
            //开启消息循环
            Looper.loop();
    
            throw new RuntimeException("Main thread loop unexpectedly exited");
        }

    调用Looper.prepareMainLooper()之后,创建静态的的Looper对象sMainLooper,并将Looper对象存放到ThreadLocal<Looper>里面。在不同线程下可以通过调用Looper.myLooper()创建自己的消息循环其实就是利用ThreadLocal<Looper>来实现的。

    Looper的准备流程图如下:

    当进入Looper.loop()之后,会读取MessageQueue里面的消息,如果消息队列为空则睡眠等待,直到通过Handler.sendMessage()将Message放入到MessageQueue才会唤醒,流程如下:

    将Message放入到MessageQueue之后,Looper.loop()则会取出Message,然后通过msg.target.dispatchMessage(msg)进入到处理消息流程:

    如此就会进入到Handler.handleMessage()里面,平时Handler的使用就是覆写Handler.handleMessage()来处理消息,调整UI的。

    PS:

    1、new Handler()无参构造函数默认调用Looper.myLooper(),如果在另外的子线程中调用而没有先调用Looper.prepare()则会抛出RuntimeException("Can't create handler inside thread that has not called Looper.prepare()")异常;

    如果在子线程中也想调用主线程中的消息循环,那么必须通过new Handler(Looper.getMainLooper())传递主线程的Looper;

    2、由于Looper.prepareMainLooper()已经在ActivityThread中调用了,如果在其他地方调用则会出错,因此Looper.prepareMainLooper()不应该被调用;

    3、如果想要使用与界面无关的消息循环,建议使用HandlerThread;

    4、如果想要使用与界面有关的消息循环,建议使用AsyncTask。

  • 相关阅读:
    【23设计模式】总结
    【JAVA】内部类,内部接口
    【JAVA】接口
    【JAVA】抽象类,抽象方法
    【JAVA】类加载器
    【JAVA】枚举
    【JAVA】序列化
    【JAVA】异常笔记
    汇编笔记_第十一章
    汇编笔记_第十章
  • 原文地址:https://www.cnblogs.com/alexthecoder/p/5098905.html
Copyright © 2020-2023  润新知