面试题线程面试

主线程中Looper的轮询死循环为何没阻塞主线程

2019-08-26  本文已影响0人  因为我的心

一、前言:

主要介绍 Looper 常见的面试题,包括以下几个问题:

  1. 造成ANR的原因
  2. 问题描述
  3. ActivityThread中main方法
  4. Looper.loop()方法无限循环
  5. 处理消息handleMessage方法
  6. loop的循环消耗性能吗?
  7. 得出结论

二、解决问题:

1. 造成ANR的原因

2. 问题描述

3. ActivityThread中main方法

public static final void main(String[] args) {
    ...
    //创建Looper和MessageQueue
    Looper.prepareMainLooper();
    ...
    //轮询器开始轮询
    Looper.loop();
    ...
}

4. Looper.loop()方法无限循环

看看Looper.loop()方法无限循环部分的代码

while (true) {
   //取出消息队列的消息,可能会阻塞
   Message msg = queue.next(); // might block
   ...
   //解析消息,分发消息
   msg.target.dispatchMessage(msg);
   ...
}

因为Android 的是由事件驱动的,looper.loop() 不断地接收事件、处理事件,每一个点击触摸或者说Activity的生命周期都是运行在 Looper.loop() 的控制之下,如果它停止了,应用也就停止了。只能是某一个消息或者说对消息的处理阻塞了 Looper.loop(),而不是 Looper.loop() 阻塞它。

5. 处理消息handleMessage方法

如下所示

public void handleMessage(Message msg) {
    if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
    switch (msg.what) {
        case LAUNCH_ACTIVITY: {
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
            final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
            r.packageInfo = getPackageInfoNoCheck(r.activityInfo.applicationInfo, r.compatInfo);
            handleLaunchActivity(r, null);
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        }
        break;
        case RELAUNCH_ACTIVITY: {
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityRestart");
            ActivityClientRecord r = (ActivityClientRecord) msg.obj;
            handleRelaunchActivity(r);
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        }
        break;
        case PAUSE_ACTIVITY:
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
            handlePauseActivity((IBinder) msg.obj, false, (msg.arg1 & 1) != 0, msg.arg2, (msg.arg1 & 2) != 0);
            maybeSnapshot();
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            break;
        case PAUSE_ACTIVITY_FINISHING:
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
            handlePauseActivity((IBinder) msg.obj, true, (msg.arg1 & 1) != 0, msg.arg2, (msg.arg1 & 1) != 0);
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            break;
        ...........
    }
}

6. loop的循环消耗性能吗?

7. 得出结论

解决这个问题优秀文章:
https://blog.csdn.net/wl1433289703/article/details/95633042

————————————————
原文链接:https://blog.csdn.net/m0_37700275/article/details/89419095

上一篇下一篇

猜你喜欢

热点阅读