程序入口为ActivityThread的main方法,源码如下:
frameworks/base/core/java/android/app/ActivityThread.java

public static void main(String[] args) {        SamplingProfilerIntegration.start();        // CloseGuard defaults to true and can be quite spammy.  We        // disable it here, but selectively enable it later (via        // StrictMode) on debug builds, but using DropBox, not logs.        CloseGuard.setEnabled(false);        Environment.initForCurrentUser();        // Set the reporter for event logging in libcore        EventLogger.setReporter(new EventLoggingReporter());        Security.addProvider(new AndroidKeyStoreProvider());        Process.setArgV0("");        Looper.prepareMainLooper();        ActivityThread thread = new ActivityThread();        thread.attach(false);        if (sMainThreadHandler == null) {            sMainThreadHandler = thread.getHandler();        }        AsyncTask.init();        if (false) {            Looper.myLooper().setMessageLogging(new                    LogPrinter(Log.DEBUG, "ActivityThread"));        }        Looper.loop();        throw new RuntimeException("Main thread loop unexpectedly exited");    }

可以看到main方法的最下面有调用Looper.loop()方法,我们看下Looper.loop()方法,源码如下:
frameworks/base/core/java/android/os/Looper.java

 /**     * Run the message queue in this thread. Be sure to call     * {@link #quit()} to end the loop.     */    public static void loop() {        final Looper me = myLooper();        if (me == null) {            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");        }        final MessageQueue queue = me.mQueue;        // Make sure the identity of this thread is that of the local process,        // and keep track of what that identity token actually is.        Binder.clearCallingIdentity();        final long ident = Binder.clearCallingIdentity();        for (;;) {            Message msg = queue.next(); // might block            if (msg == null) {                // No message indicates that the message queue is quitting.                return;            }            // This must be in a local variable, in case a UI event sets the logger            Printer logging = me.mLogging;            if (logging != null) {                logging.println(">>>>> Dispatching to " + msg.target + " " +                        msg.callback + ": " + msg.what);            }            msg.target.dispatchMessage(msg);            if (logging != null) {                logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);            }            // Make sure that during the course of dispatching the            // identity of the thread wasn't corrupted.            final long newIdent = Binder.clearCallingIdentity();            if (ident != newIdent) {                Log.wtf(TAG, "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();        }    }

可以看到looper方法中有个for死循环中next方法是阻塞的,那么为什么这里阻塞不会造成主线程卡死然后ANR呢?参考了好多资料都比较抽象难懂,这里自己用“土方子”从反面考虑这个问题

  • 写了一个demo,点击按钮执行如下代码
Looper.getMainLooper().quit(); 

退出looper后,handler发送的所有消息都会失败,同时这个UI线程就会立刻终止;测试了下点击按钮,这个app会立刻关闭;ActivityThread的main方法主要功能就是做消息循环,必须一直存在,一旦退出消息循环,app就会立刻关闭;

  • 那为什么阻塞还可以和主线程进行交互呢?
    仔细观察ActivityThread中的main方法中Looper.loop();在方法的最后位置,放在main方法?如果在其后面再添加东西那么肯定不会执行。那我理解的是main方法中Looper.loop()这句前所有的UI交互逻辑应该都在这一部分,这一部分是不会受到loop()方法阻塞影响;并且阻塞不代表不运行,只是等待状态;在ActivityThread类中的内部类H继承Handler,里面实现了不同的消息处理的case,只要通过handler发送消息,messagequeue中有message,只要保证有消息的时候能够立刻处理,程序是不会无响应的
    frameworks/base/core/java/android/app/ActivityThread.java
private class H extends Handler {        public static final int LAUNCH_ACTIVITY         = 100;        public static final int PAUSE_ACTIVITY          = 101;        public static final int PAUSE_ACTIVITY_FINISHING= 102;        public static final int STOP_ACTIVITY_SHOW      = 103;        public static final int STOP_ACTIVITY_HIDE      = 104;        public static final int SHOW_WINDOW             = 105;        public static final int HIDE_WINDOW             = 106;        public static final int RESUME_ACTIVITY         = 107;        public static final int SEND_RESULT             = 108;        public static final int DESTROY_ACTIVITY        = 109;        public static final int BIND_APPLICATION        = 110;        public static final int EXIT_APPLICATION        = 111;        public static final int NEW_INTENT              = 112;        public static final int RECEIVER                = 113;        public static final int CREATE_SERVICE          = 114;        public static final int SERVICE_ARGS            = 115;        public static final int STOP_SERVICE            = 116;        public static final int REQUEST_THUMBNAIL       = 117;        public static final int CONFIGURATION_CHANGED   = 118;        public static final int CLEAN_UP_CONTEXT        = 119;        public static final int GC_WHEN_IDLE            = 120;        public static final int BIND_SERVICE            = 121;        public static final int UNBIND_SERVICE          = 122;        public static final int DUMP_SERVICE            = 123;        public static final int LOW_MEMORY              = 124;        public static final int ACTIVITY_CONFIGURATION_CHANGED = 125;        public static final int RELAUNCH_ACTIVITY       = 126;        public static final int PROFILER_CONTROL        = 127;        public static final int CREATE_BACKUP_AGENT     = 128;        public static final int DESTROY_BACKUP_AGENT    = 129;        public static final int SUICIDE                 = 130;        public static final int REMOVE_PROVIDER         = 131;        public static final int ENABLE_JIT              = 132;        public static final int DISPATCH_PACKAGE_BROADCAST = 133;        public static final int SCHEDULE_CRASH          = 134;        public static final int DUMP_HEAP               = 135;        public static final int DUMP_ACTIVITY           = 136;        public static final int SLEEPING                = 137;        public static final int SET_CORE_SETTINGS       = 138;        public static final int UPDATE_PACKAGE_COMPATIBILITY_INFO = 139;        public static final int TRIM_MEMORY             = 140;        public static final int DUMP_PROVIDER           = 141;        public static final int UNSTABLE_PROVIDER_DIED  = 142;        public static final int REQUEST_ASSIST_CONTEXT_EXTRAS = 143;        public static final int TRANSLUCENT_CONVERSION_COMPLETE = 144;        public static final int INSTALL_PROVIDER        = 145;        String codeToString(int code) {            if (DEBUG_MESSAGES) {                switch (code) {                    case LAUNCH_ACTIVITY: return "LAUNCH_ACTIVITY";                    case PAUSE_ACTIVITY: return "PAUSE_ACTIVITY";                    case PAUSE_ACTIVITY_FINISHING: return "PAUSE_ACTIVITY_FINISHING";                    case STOP_ACTIVITY_SHOW: return "STOP_ACTIVITY_SHOW";                    case STOP_ACTIVITY_HIDE: return "STOP_ACTIVITY_HIDE";                    case SHOW_WINDOW: return "SHOW_WINDOW";                    case HIDE_WINDOW: return "HIDE_WINDOW";                    case RESUME_ACTIVITY: return "RESUME_ACTIVITY";                    case SEND_RESULT: return "SEND_RESULT";                    case DESTROY_ACTIVITY: return "DESTROY_ACTIVITY";                    case BIND_APPLICATION: return "BIND_APPLICATION";                    case EXIT_APPLICATION: return "EXIT_APPLICATION";                    case NEW_INTENT: return "NEW_INTENT";                    case RECEIVER: return "RECEIVER";                    case CREATE_SERVICE: return "CREATE_SERVICE";                    case SERVICE_ARGS: return "SERVICE_ARGS";                    case STOP_SERVICE: return "STOP_SERVICE";                    case REQUEST_THUMBNAIL: return "REQUEST_THUMBNAIL";                    case CONFIGURATION_CHANGED: return "CONFIGURATION_CHANGED";                    case CLEAN_UP_CONTEXT: return "CLEAN_UP_CONTEXT";                    case GC_WHEN_IDLE: return "GC_WHEN_IDLE";                    case BIND_SERVICE: return "BIND_SERVICE";                    case UNBIND_SERVICE: return "UNBIND_SERVICE";                    case DUMP_SERVICE: return "DUMP_SERVICE";                    case LOW_MEMORY: return "LOW_MEMORY";                    case ACTIVITY_CONFIGURATION_CHANGED: return "ACTIVITY_CONFIGURATION_CHANGED";                    case RELAUNCH_ACTIVITY: return "RELAUNCH_ACTIVITY";                    case PROFILER_CONTROL: return "PROFILER_CONTROL";                    case CREATE_BACKUP_AGENT: return "CREATE_BACKUP_AGENT";                    case DESTROY_BACKUP_AGENT: return "DESTROY_BACKUP_AGENT";                    case SUICIDE: return "SUICIDE";                    case REMOVE_PROVIDER: return "REMOVE_PROVIDER";                    case ENABLE_JIT: return "ENABLE_JIT";                    case DISPATCH_PACKAGE_BROADCAST: return "DISPATCH_PACKAGE_BROADCAST";                    case SCHEDULE_CRASH: return "SCHEDULE_CRASH";                    case DUMP_HEAP: return "DUMP_HEAP";                    case DUMP_ACTIVITY: return "DUMP_ACTIVITY";                    case SLEEPING: return "SLEEPING";                    case SET_CORE_SETTINGS: return "SET_CORE_SETTINGS";                    case UPDATE_PACKAGE_COMPATIBILITY_INFO: return "UPDATE_PACKAGE_COMPATIBILITY_INFO";                    case TRIM_MEMORY: return "TRIM_MEMORY";                    case DUMP_PROVIDER: return "DUMP_PROVIDER";                    case UNSTABLE_PROVIDER_DIED: return "UNSTABLE_PROVIDER_DIED";                    case REQUEST_ASSIST_CONTEXT_EXTRAS: return "REQUEST_ASSIST_CONTEXT_EXTRAS";                    case TRANSLUCENT_CONVERSION_COMPLETE: return "TRANSLUCENT_CONVERSION_COMPLETE";                    case INSTALL_PROVIDER: return "INSTALL_PROVIDER";                }            }            return Integer.toString(code);        }        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");                    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 != 0, msg.arg2);                    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 != 0, msg.arg2);                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);                    break;                case STOP_ACTIVITY_SHOW:                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStop");                    handleStopActivity((IBinder)msg.obj, true, msg.arg2);                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);                    break;                case STOP_ACTIVITY_HIDE:                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStop");                    handleStopActivity((IBinder)msg.obj, false, msg.arg2);                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);                    break;                case SHOW_WINDOW:                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityShowWindow");                    handleWindowVisibility((IBinder)msg.obj, true);                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);                    break;                case HIDE_WINDOW:                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityHideWindow");                    handleWindowVisibility((IBinder)msg.obj, false);                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);                    break;                case RESUME_ACTIVITY:                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityResume");                    handleResumeActivity((IBinder)msg.obj, true,                            msg.arg1 != 0, true);                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);                    break;                case SEND_RESULT:                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityDeliverResult");                    handleSendResult((ResultData)msg.obj);                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);                    break;                case DESTROY_ACTIVITY:                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityDestroy");                    handleDestroyActivity((IBinder)msg.obj, msg.arg1 != 0,                            msg.arg2, false);                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);                    break;                case BIND_APPLICATION:                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");                    AppBindData data = (AppBindData)msg.obj;                    handleBindApplication(data);                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);                    break;                case EXIT_APPLICATION:                    if (mInitialApplication != null) {                        mInitialApplication.onTerminate();                    }                    Looper.myLooper().quit();                    break;                case NEW_INTENT:                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityNewIntent");                    handleNewIntent((NewIntentData)msg.obj);                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);                    break;                case RECEIVER:                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveComp");                    handleReceiver((ReceiverData)msg.obj);                    maybeSnapshot();                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);                    break;                case CREATE_SERVICE:                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceCreate");                    handleCreateService((CreateServiceData)msg.obj);                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);                    break;                case BIND_SERVICE:                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceBind");                    handleBindService((BindServiceData)msg.obj);                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);                    break;                case UNBIND_SERVICE:                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceUnbind");                    handleUnbindService((BindServiceData)msg.obj);                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);                    break;                case SERVICE_ARGS:                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceStart");                    handleServiceArgs((ServiceArgsData)msg.obj);                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);                    break;                case STOP_SERVICE:                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceStop");                    handleStopService((IBinder)msg.obj);                    maybeSnapshot();                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);                    break;                case REQUEST_THUMBNAIL:                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "requestThumbnail");                    handleRequestThumbnail((IBinder)msg.obj);                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);                    break;                case CONFIGURATION_CHANGED:                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "configChanged");                    mCurDefaultDisplayDpi = ((Configuration)msg.obj).densityDpi;                    handleConfigurationChanged((Configuration)msg.obj, null);                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);                    break;                case CLEAN_UP_CONTEXT:                    ContextCleanupInfo cci = (ContextCleanupInfo)msg.obj;                    cci.context.performFinalCleanup(cci.who, cci.what);                    break;                case GC_WHEN_IDLE:                    scheduleGcIdler();                    break;                case DUMP_SERVICE:                    handleDumpService((DumpComponentInfo)msg.obj);                    break;                case LOW_MEMORY:                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "lowMemory");                    handleLowMemory();                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);                    break;                case ACTIVITY_CONFIGURATION_CHANGED:                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityConfigChanged");                    handleActivityConfigurationChanged((IBinder)msg.obj);                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);                    break;                case PROFILER_CONTROL:                    handleProfilerControl(msg.arg1 != 0, (ProfilerControlData)msg.obj, msg.arg2);                    break;                case CREATE_BACKUP_AGENT:                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backupCreateAgent");                    handleCreateBackupAgent((CreateBackupAgentData)msg.obj);                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);                    break;                case DESTROY_BACKUP_AGENT:                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backupDestroyAgent");                    handleDestroyBackupAgent((CreateBackupAgentData)msg.obj);                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);                    break;                case SUICIDE:                    Process.killProcess(Process.myPid());                    break;                case REMOVE_PROVIDER:                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "providerRemove");                    completeRemoveProvider((ProviderRefCount)msg.obj);                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);                    break;                case ENABLE_JIT:                    ensureJitEnabled();                    break;                case DISPATCH_PACKAGE_BROADCAST:                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastPackage");                    handleDispatchPackageBroadcast(msg.arg1, (String[])msg.obj);                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);                    break;                case SCHEDULE_CRASH:                    throw new RemoteServiceException((String)msg.obj);                case DUMP_HEAP:                    handleDumpHeap(msg.arg1 != 0, (DumpHeapData)msg.obj);                    break;                case DUMP_ACTIVITY:                    handleDumpActivity((DumpComponentInfo)msg.obj);                    break;                case DUMP_PROVIDER:                    handleDumpProvider((DumpComponentInfo)msg.obj);                    break;                case SLEEPING:                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "sleeping");                    handleSleeping((IBinder)msg.obj, msg.arg1 != 0);                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);                    break;                case SET_CORE_SETTINGS:                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "setCoreSettings");                    handleSetCoreSettings((Bundle) msg.obj);                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);                    break;                case UPDATE_PACKAGE_COMPATIBILITY_INFO:                    handleUpdatePackageCompatibilityInfo((UpdateCompatibilityData)msg.obj);                    break;                case TRIM_MEMORY:                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "trimMemory");                    handleTrimMemory(msg.arg1);                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);                    break;                case UNSTABLE_PROVIDER_DIED:                    handleUnstableProviderDied((IBinder)msg.obj, false);                    break;                case REQUEST_ASSIST_CONTEXT_EXTRAS:                    handleRequestAssistContextExtras((RequestAssistContextExtras)msg.obj);                    break;                case TRANSLUCENT_CONVERSION_COMPLETE:                    handleTranslucentConversionComplete((IBinder)msg.obj, msg.arg1 == 1);                    break;                case INSTALL_PROVIDER:                    handleInstallProvider((ProviderInfo) msg.obj);                    break;            }            if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + codeToString(msg.what));        }

纯属个人理解,其他参考资料见下面链接
知乎-Android中为什么主线程不会因为Looper.loop()里的死循环卡死?
Looper.loop()一直死循环
Android中为什么主线程不会因为Looper.loop()里的死循环阻塞?

更多相关文章

  1. Android强制设置横屏或竖屏
  2. Android获取状态栏高度的方法
  3. android-使App全屏 - 随心
  4. android中遍历arrayList的四种方法
  5. android实现猜扑克牌小游戏(改进:每次只可以选择一张)
  6. Glide使用方法汇总
  7. 【android】对canvas的translate(),save(),restore()方法的理解
  8. Android(安卓)Jetpack之Lifecycle的源码分析
  9. Android性能检测--traceview工具各个参数的意思

随机推荐

  1. 如何配置ubuntu 64安装环境(转自source.an
  2. Design各控件的搭配使用2
  3. Android 判断输入的年月日是否合法-正则
  4. android listview 同时监听click和longcl
  5. android 向SD卡写入数据
  6. Android NDK 安装 运行
  7. Android 限制edittext 整数和小数位数 过
  8. android sqlite查询数据表的字段与相关属
  9. 转:android笔记之contacts(通讯录)数据库
  10. Android系统去掉 USB插入调试确认框