这个问题其实已经在知乎有大神回答了:Android中为什么主线程不会因为Looper.loop()里的死循环卡死?

 public static void main(String[] args) {      ...        Looper.prepareMainLooper();        ActivityThread thread = new ActivityThread();        thread.attach(false);        if (sMainThreadHandler == null) {            sMainThreadHandler = thread.getHandler();        }       ...        Looper.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;      ...        for (;;) {            Message msg = queue.next(); // might block         ...            msg.target.dispatchMessage(msg);         ...            msg.recycleUnchecked();        }    }

这里有2个问题:

1,一个死循环为什么没有把内存撑爆造成卡顿。

2,既然是死循环那后面的生命周期方法是怎么执行的。

第一个问题在Android的Handler机制详解2_native就回答了,MessageQueue.next()并没有一直在那里“傻转”它是通过调用nativePollOnce()这个navtive方法造成了阻塞,阻塞最终是通过epoll机制实现,每当我们向消息队列发送事件时,最终会间接向管道的“写入端”写入数据,于是epoll通过管道的“读取端”立即就感知到了风吹草动,epoll_wait()在等到事件后,随即进行相应的事件处理。

其实主线程的这个死循环是非常有必要的,在CPU看来进程或线程无非就是一段可执行的代码,当可执行代码执行完成

后,线程生命周期便该终止了,线程退出。而对于主线程,我们是绝不希望会被运行一段时间,自己就退出,那么如何保证能一直存活呢?简单做法就是可执行代码是能一直执行下去的,死循环便能保证不会被退出

第二个问题答案是创建新的线程事实上,会在进入死循环之前便创建了新binder线程,在代码ActivityThread.main()中:

public static void main(String[] args) {        ....        //创建Looper和MessageQueue对象,用于处理主线程的消息        Looper.prepareMainLooper();        //创建ActivityThread对象        ActivityThread thread = new ActivityThread();         //建立Binder通道 (创建新线程)        thread.attach(false);        Looper.loop(); //消息循环运行        throw new RuntimeException("Main thread loop unexpectedly exited");    }
thread.attach(false);便会创建一个Binder线程(具体是指ApplicationThread,Binder的服务端,用于接收系统服务AMS发送来的事件),该Binder线程通过Handler将Message发送给主线程。由于ApplicationThread是基于IBinder接口,都是binder线程,binder线程的创建与销毁都是由binder驱动来决定的,每个进程binder线程个数的上限为16。

ActivityThread.attach(boolean)

 private void attach(boolean system) {        sCurrentActivityThread = this;        mSystemThread = system;        if (!system) {           ...            final IActivityManager mgr = ActivityManagerNative.getDefault();            try {                mgr.attachApplication(mAppThread);            } catch (RemoteException ex) {                // Ignore            }           ...        } else {           ...        }       ...    }

ActivityManagerNative.getDefault()

 /**     * Retrieve the system's default/global activity manager.     */    static public IActivityManager getDefault() {        return gDefault.get();    }

ActivityManagerNative.gDefault

  private static final Singleton gDefault = new Singleton() {        protected IActivityManager create() {            IBinder b = ServiceManager.getService("activity");            if (false) {                Log.v("ActivityManager", "default service binder = " + b);            }            IActivityManager am = asInterface(b);            if (false) {                Log.v("ActivityManager", "default service = " + am);            }            return am;        }    };}

ActivityManagetNative.asInterface(IBinder)

  static public IActivityManager asInterface(IBinder obj) {        if (obj == null) {            return null;        }        IActivityManager in =            (IActivityManager)obj.queryLocalInterface(descriptor);        if (in != null) {            return in;        }        return new ActivityManagerProxy(obj);    }

从上面方法就可以看出,ActivityThread.attach()中final IActivityManager mgr = ActivityManagerNative.getDefault();得到的是ActivityManagerProxy().接下看看ActivityManagerProxy.attachApplication(IApplication)。

ActivityManagerProxy.attachApplication(IApplication)

 public void attachApplication(IApplicationThread app) throws RemoteException    {        Parcel data = Parcel.obtain();        Parcel reply = Parcel.obtain();        data.writeInterfaceToken(IActivityManager.descriptor);        data.writeStrongBinder(app.asBinder());        mRemote.transact(ATTACH_APPLICATION_TRANSACTION, data, reply, 0);        reply.readException();        data.recycle();        reply.recycle();    }

ActivityManagerProxy是IActivityManager的代理类,通过Binder通信过程中,提供了一个IActivityManager服务接口,ActivityManagerProxy类与ActivityManagerService类都实现了IActivityManager接口。ActivityManagerProxy作为binder通信的客户端,ActivityManagerService作为binder通信的服务端,ActivityManagerProxy.attachApplication()最终调用ActivityManagerService.attachApplication()。

ActivityManagerService.attachApplication(IApplicationThread)

 @Override    public final void attachApplication(IApplicationThread thread) {        synchronized (this) {            int callingPid = Binder.getCallingPid();            final long origId = Binder.clearCallingIdentity();            attachApplicationLocked(thread, callingPid);            Binder.restoreCallingIdentity(origId);        }    }

最终ApplicationThread被发送到了ActivityManagerService。ApplicationThread作为服务端,ActivityManagerService所调用的方法最终都会执行ApplicationThread中的方法。

ApplicationThread.java

 private class ApplicationThread extends ApplicationThreadNative {        private static final String DB_INFO_FORMAT = "  %8s %8s %14s %14s  %s";        private int mLastProcessState = -1;       ...        public final void schedulePauseActivity(IBinder token, boolean finished,                boolean userLeaving, int configChanges, boolean dontReport) {            sendMessage(                    finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,                    token,                    (userLeaving ? 1 : 0) | (dontReport ? 2 : 0),                    configChanges);        }        public final void scheduleStopActivity(IBinder token, boolean showWindow,                int configChanges) {           sendMessage(                showWindow ? H.STOP_ACTIVITY_SHOW : H.STOP_ACTIVITY_HIDE,                token, 0, configChanges);        }       ...        public final void scheduleResumeActivity(IBinder token, int processState,                boolean isForward, Bundle resumeArgs) {            updateProcessState(processState, false);            sendMessage(H.RESUME_ACTIVITY, token, isForward ? 1 : 0);        }       ...        public final void scheduleDestroyActivity(IBinder token, boolean finishing,                int configChanges) {            sendMessage(H.DESTROY_ACTIVITY, token, finishing ? 1 : 0,                    configChanges);        }        public final void scheduleReceiver(Intent intent, ActivityInfo info,                CompatibilityInfo compatInfo, int resultCode, String data, Bundle extras,                boolean sync, int sendingUser, int processState) {            updateProcessState(processState, false);            ReceiverData r = new ReceiverData(intent, resultCode, data, extras,                    sync, false, mAppThread.asBinder(), sendingUser);            r.info = info;            r.compatInfo = compatInfo;            sendMessage(H.RECEIVER, r);        }        ...        public final void scheduleCreateService(IBinder token,                ServiceInfo info, CompatibilityInfo compatInfo, int processState) {            updateProcessState(processState, false);            CreateServiceData s = new CreateServiceData();            s.token = token;            s.info = info;            s.compatInfo = compatInfo;            sendMessage(H.CREATE_SERVICE, s);        }        public final void scheduleBindService(IBinder token, Intent intent,                boolean rebind, int processState) {            updateProcessState(processState, false);            BindServiceData s = new BindServiceData();            s.token = token;            s.intent = intent;            s.rebind = rebind;            if (DEBUG_SERVICE)                Slog.v(TAG, "scheduleBindService token=" + token + " intent=" + intent + " uid="                        + Binder.getCallingUid() + " pid=" + Binder.getCallingPid());            sendMessage(H.BIND_SERVICE, s);        }         ...        public final void scheduleStopService(IBinder token) {            sendMessage(H.STOP_SERVICE, token);        }        ...        public void scheduleConfigurationChanged(Configuration config) {            updatePendingConfiguration(config);            sendMessage(H.CONFIGURATION_CHANGED, config);        }       ...    }

看一看sendMessage()方法

ActivityThread.sendMessage()

  private void sendMessage(int what, Object obj) {        sendMessage(what, obj, 0, 0, false);    }    private void sendMessage(int what, Object obj, int arg1) {        sendMessage(what, obj, arg1, 0, false);    }    private void sendMessage(int what, Object obj, int arg1, int arg2) {        sendMessage(what, obj, arg1, arg2, false);    }    private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {        if (DEBUG_MESSAGES) Slog.v(            TAG, "SCHEDULE " + what + " " + mH.codeToString(what)            + ": " + arg1 + " / " + obj);        Message msg = Message.obtain();        msg.what = what;        msg.obj = obj;        msg.arg1 = arg1;        msg.arg2 = arg2;        if (async) {            msg.setAsynchronous(true);        }        mH.sendMessage(msg);    }

最终都是走mH.sendMessage()

H.java

 private class H extends Handler {        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 RESUME_ACTIVITY         = 107;        public static final int DESTROY_ACTIVITY        = 109;        public static final int NEW_INTENT              = 112;        public static final int RECEIVER                = 113;        public static final int CREATE_SERVICE          = 114;        public static final int STOP_SERVICE            = 116;        ...        String codeToString(int code) {           ...            return Integer.toString(code);        }        public void handleMessage(Message msg) {            switch (msg.what) {             ...                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 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 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 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 STOP_SERVICE:                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceStop");                    handleStopService((IBinder)msg.obj);                    maybeSnapshot();                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);                    break;                ...                   }         }    }

接着看PAUSE_ACTIVITY这个条件分支中的方法调用。

ActivityThread.handlePauseActivity()

 private void handlePauseActivity(IBinder token, boolean finished,            boolean userLeaving, int configChanges, boolean dontReport) {        ActivityClientRecord r = mActivities.get(token);        if (r != null) {            if (userLeaving) {                performUserLeavingActivity(r);            }            r.activity.mConfigChangeFlags |= configChanges;            performPauseActivity(token, finished, r.isPreHoneycomb());            // Make sure any pending writes are now committed.            if (r.isPreHoneycomb()) {                QueuedWork.waitToFinish();            }            // Tell the activity manager we have paused.            if (!dontReport) {                try {                    ActivityManagerNative.getDefault().activityPaused(token);                } catch (RemoteException ex) {                }            }            mSomeActivitiesChanged = true;        }    }

ActivityThread.performPauseActivity()

  final Bundle performPauseActivity(IBinder token, boolean finished,            boolean saveState) {        ActivityClientRecord r = mActivities.get(token);        return r != null ? performPauseActivity(r, finished, saveState) : null;    }    final Bundle performPauseActivity(ActivityClientRecord r, boolean finished, boolean saveState) {       ...        try {            // Next have the activity save its current state and managed dialogs...            if (!r.activity.mFinished && saveState) {                callCallActivityOnSaveInstanceState(r);            }            // Now we are idle.            r.activity.mCalled = false;            mInstrumentation.callActivityOnPause(r.activity);            EventLog.writeEvent(LOG_AM_ON_PAUSE_CALLED, UserHandle.myUserId(),                    r.activity.getComponentName().getClassName());            if (!r.activity.mCalled) {                throw new SuperNotCalledException("");            }        } catch (SuperNotCalledException e) {            throw e;        } catch (Exception e) {            if (!mInstrumentation.onException(r.activity, e)) {                throw new RuntimeException("", e);            }        }       ...        return !r.activity.mFinished && saveState ? r.state : null;    }

Instrumentation.callActivityOnPause(Activity)

public void callActivityOnPause(Activity activity) {        activity.performPause();    }

Activity.performPause()

    final void performPause() {        mDoReportFullyDrawn = false;        mFragments.dispatchPause();        mCalled = false;        onPause();        mResumed = false;        if (!mCalled && getApplicationInfo().targetSdkVersion >= android.os.Build.VERSION_CODES.GINGERBREAD) {            throw new SuperNotCalledException("Activity " + mComponent.toShortString()+" did not call through to super.onPause()");        }        mResumed = false;    }
到此终于调到了Activity的onPause这个生命周期方法。通过上面源码一个一个的跟踪也完美的解答了第二个问题。虽然Looper.looper()是一个死循环,但是在进入死循环之前就一个创建了一个Binder线程(ApplicationThread)作为服务端用来接受ActivityManagerService发来的事件,然后通过handler发送给主线程进行处理。

更多相关文章

  1. Android(安卓)Vibrator使用
  2. Android之Handler用法总结
  3. Android开发之消息处理机制(一)——Handler
  4. Android异步加载图像小结 (含线程池,缓存方法)
  5. android 面试题集
  6. [Innost]Android深入浅出之Binder机制
  7. Android(安卓)常用组价申明及使用简集
  8. 利用Handler来更新android的UI
  9. 利用Handler来更新android的UI

随机推荐

  1. Android 监听前台后台切换
  2. Unity各平台上读写文件-Android例子
  3. Android Usb源码分析
  4. Ubuntu下编译android所需ffmpeg的so库
  5. Android StateMachine记录
  6. android使用web加载网页的js问题
  7. Android常用网址
  8. Android WebView untold stories
  9. Android(安卓)Studio如何设置自动import
  10. android memory 优化