当前位置: 移动技术网 > 移动技术>移动开发>Android > Looper.loop()方法跑的是死循环, 为什么我们的Activity生命周期方法还能在主线程中运行?

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

2020年07月09日  | 移动技术网移动技术  | 我要评论

参考: 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
在这里插入图片描述

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

在这里插入图片描述

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

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网