欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Looper.loop()方法跑的是死循环, 为什么我们的Activity生命周期方法还能在主线程中运行?

程序员文章站 2022-06-22 08:58:53
参考: https://www.jianshu.com/p/733b1cc9b457ActivityThread就是我们常说的主线程或UI线程,ActivityThread的main方法是整个APP的入口MainLooper在它的main方法中被创建。 //ActivityThread的main方法 public static void main(String[] args) { ...... Looper.prepareMainLooper(); //...

参考: https://www.jianshu.com/p/733b1cc9b457

ActivityThread就是我们常说的主线程或UI线程,ActivityThread的main方法是整个APP的入口
MainLooper在它的main方法中被创建。

    //ActivityThread的main方法
    public static void main(String[] args) {
        ......
        Looper.prepareMainLooper();  //创建MainLooper
        ActivityThread thread = new ActivityThread();
        //在attach方法中会完成Application对象的初始化,然后调用Application的onCreate()方法
        thread.attach(false);

        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
        }
        ......
        Looper.loop();  //开启循环
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }


Looper.loop()方法跑的是死循环, 为什么我们的Activity生命周期方法还能在主线程中运行?

看下面代码
framworks\base\core\java\android\os\Looper.java
Looper.loop()

public static final void loop() {
        Looper me = myLooper();
        MessageQueue queue = me.mQueue;
        Binder.clearCallingIdentity();
        final long ident = Binder.clearCallingIdentity();
        //开启死循环
        while (true) {
            //该方法是阻塞只到有新的消息到来
            Message msg = queue.next(); // might block
            if (msg != null) {
                if (msg.target == null) {
                    return;
                }
                if (me.mLogging!= null) me.mLogging.println(
                        ">>>>> Dispatching to " + msg.target + " "
                        + msg.callback + ": " + msg.what
                        );
                 // 分发处理消息, target是一个Handler类      
                msg.target.dispatchMessage(msg);
                
                if (me.mLogging!= null) me.mLogging.println(  "<<<<< Finished to    " + msg.target + " " + msg.callback);
                final long newIdent = Binder.clearCallingIdentity();
                if (ident != newIdent) {
                    Log.wtf("Looper", "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.recycle();
            }
        }
    }

Message msg = queue.next(); // might block
这句没有消息来的时候确实是阻塞的
但是这里不仅仅接收我们自己发送的消息, 还会接收系统发送过来的消息, 比如生命周期发生变化的消息.
当收到消息后就会执行下面这句:
msg.target.dispatchMessage(msg); //target是一个Handler类
这个target就是我们自己或者系统传过来的Handler, 他们不是同一个Handler,
所以会各自执行自己覆盖的handleMessage(msg)方法

framworks\base\core\java\android\os\Handler.java
handler.dispatchMessage()

public void dispatchMessage(Message msg) {
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);
        }
    }

Activity的生命周期是怎么实现在死循环体外能够执行起来的?
ActivityThread的内部类H继承于Handler,通过handler消息机制,简单说Handler机制用于同一个进程的线程间通信。
Activity的生命周期都是依靠主线程的Looper.loop,当收到不同Message时则采用相应措施:
在H.handleMessage(msg)方法中,根据接收到不同的msg,执行相应的生命周期。
比如收到msg=H.LAUNCH_ACTIVITY,则调用ActivityThread.handleLaunchActivity()方法,最终会通过反射机制,创建Activity实例,然后再执行Activity.onCreate()等方法;
再比如收到msg=H.PAUSE_ACTIVITY,则调用ActivityThread.handlePauseActivity()方法,最终会执行Activity.onPause()等方法。 上述过程,我只挑核心逻辑讲,真正该过程远比这复杂。

我们可以断点调试验证一下,是不是上面所说那样?

点击一个button发生一条自定义消息

public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    Handler handler = new Handler(){
        @Override
        public void handleMessage(@NonNull Message msg) {
        }
   };

    public void click(View view) {
        Message message = Message.obtain();
        message.what = 100;
        message.obj = "我是自定义的消息";
        handler.sendMessage(message);
    }
}

在类Handler的handleMessage()方法中设置断点
点击按钮, 会收到自己定义的message
Looper.loop()方法跑的是死循环, 为什么我们的Activity生命周期方法还能在主线程中运行?

当我按下手机Home键, 我会收到一条包含 target=android.app.ActivityThread$H 的消息

Looper.loop()方法跑的是死循环, 为什么我们的Activity生命周期方法还能在主线程中运行?

frameworks\base\core\java\android\app\ActivityThread.java
H类是一个ActivityThread的内部类,继承Handler

private final class H extends Handler {
        public static final int LAUNCH_ACTIVITY         = 100;
        public static final int PAUSE_ACTIVITY          = 101;
     .......
      
        String codeToString(int code) {
            if (DEBUG_MESSAGES) {
                switch (code) {
                    case LAUNCH_ACTIVITY: return "LAUNCH_ACTIVITY";
                    case PAUSE_ACTIVITY: return "PAUSE_ACTIVITY";
                   ......
                }
            }
            return "(unknown)";
        }
        public void handleMessage(Message msg) {
            if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + msg.what);
            switch (msg.what) {
                case LAUNCH_ACTIVITY: {
                    ActivityClientRecord r = (ActivityClientRecord)msg.obj;
                    r.packageInfo = getPackageInfoNoCheck(r.activityInfo.applicationInfo);
                    handleLaunchActivity(r, null);
                } break;
                case PAUSE_ACTIVITY:
                    handlePauseActivity((IBinder)msg.obj, false, msg.arg1 != 0, msg.arg2);
                    maybeSnapshot();
                    break;
               ......
            }
            if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + msg.what);
        }
    }

本文地址:https://blog.csdn.net/csdm_admin/article/details/107164741