美文网首页
从源码的角度描述Activity的启动过程

从源码的角度描述Activity的启动过程

作者: 淡雅如兰_往事随风 | 来源:发表于2018-04-02 11:13 被阅读0次

    从源码的角度描述Activity的启动过程

    Activity作为Android四大组件之一,也是我们平时开发中使用的最多的组件。作为四大组件中最为重要的老大,Activity究竟是如何启动的呢?这篇文章从源码的角度简单的为大家进行解析。(PS:本文源码基于7.0系统)

    一般启动Activity有两种方法,这里就不再详细说这两种方法了,但是他们都是调用了同样的一个逻辑startActivity()方法。所以我们分析Activity的启动流程就从这个方法开始。请看下面startActivity()的源码:

    @Override

        public void startActivity(Intent intent) {

            this.startActivity(intent, null);

        }

        @Override

        public void startActivity(Intent intent, @Nullable Bundle options) {

            if (options != null) {

                startActivityForResult(intent, -1, options);

            } else {

                // Note we want to go through this call for compatibility with

                // applications that may have overridden the method.

                startActivityForResult(intent, -1);

            }

        }

    可以看到startActivity()有多种重载方法,但是最终调用的还是startActivityForResult()方法。下面我们来看看源码中startActivityForResult()的实现:

    public void startActivityForResult(@RequiresPermission Intent intent, int requestCode) {

            startActivityForResult(intent, requestCode, null);

        }

        public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,

                @Nullable Bundle options) {

            //mParent是一个Activity对象,表示该Activity是否由父Activity启动

            if (mParent == null) {

                //这里会启动新的Activity,核心功能都在mMainThread.getApplicationThread()中完成 

                Instrumentation.ActivityResult ar =

                    mInstrumentation.execStartActivity(

                        this, mMainThread.getApplicationThread(), mToken, this,

                        intent, requestCode, options);

                if (ar != null) {

                    //发送结果,即onActivityResult会被调用 

                    mMainThread.sendActivityResult(

                        mToken, mEmbeddedID, requestCode, ar.getResultCode(),

                        ar.getResultData());

                }

                //这里就是判断requestCode的逻辑

                if (requestCode >= 0) {

                    // If this start is requesting a result, we can avoid making

                    // the activity visible until the result is received.  Setting

                    // this code during onCreate(Bundle savedInstanceState) or onResume() will keep the

                    // activity hidden during this time, to avoid flickering.

                    // This can only be done when a result is requested because

                    // that guarantees we will get information back when the

                    // activity is finished, no matter what happens to it.

                    mStartedActivity = true;

                }

                cancelInputsAndStartExitTransition(options);

                // TODO Consider clearing/flushing other event sources and events for child windows.

            } else {

                if (options != null) {

                    mParent.startActivityFromChild(this, intent, requestCode, options);

                } else {

                    // Note we want to go through this method for compatibility with

                    // existing applications that may have overridden it.

                    mParent.startActivityFromChild(this, intent, requestCode);

                }

            }

        }

    在startActivityForResult()方法中,首先会判断该Activity是否由父Activity启动,即mParent,如果他是第一个Activity,就会调用Instrumentation的execStartActivity()方法,下面看看这个方法的源码:

      public ActivityResult execStartActivity(

                Context who, IBinder contextThread, IBinder token, Activity target,

                Intent intent, int requestCode, Bundle options) {

            IApplicationThread whoThread = (IApplicationThread) contextThread;

            Uri referrer = target != null ? target.onProvideReferrer() : null;

            if (referrer != null) {

                intent.putExtra(Intent.EXTRA_REFERRER, referrer);

            }

            if (mActivityMonitors != null) {

                synchronized (mSync) {

                    final int N = mActivityMonitors.size();

                    for (int i=0; i

                        final ActivityMonitor am = mActivityMonitors.get(i);

                        if (am.match(who, null, intent)) {

                            am.mHits++;

                            if (am.isBlocking()) {

                                return requestCode >= 0 ? am.getResult() : null;

                            }

                            break;

                        }

                    }

                }

            }

            try {

                intent.migrateExtraStreamToClipData();

                intent.prepareToLeaveProcess(who);

                int result = ActivityManagerNative.getDefault()

                    .startActivity(whoThread, who.getBasePackageName(), intent,

                            intent.resolveTypeIfNeeded(who.getContentResolver()),

                            token, target != null ? target.mEmbeddedID : null,

                            requestCode, 0, null, options);

                checkStartActivityResult(result, intent);

            } catch (RemoteException e) {

                throw new RuntimeException("Failure from system", e);

            }

            return null;

        }

    由源码可以看出这个方法的核心代码是调用了ActivityManagerNative.getDefault().startActivity(),接着看看getDefault()的源码

      static public IActivityManager getDefault() {

            return gDefault.get();

        }

        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;

            }

        };

    看上面的代码,IActivityManager 调用了asInterface() 方法,它的源码:

        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);

        }

    public ActivityManagerProxy(IBinder remote)

        {

            mRemote = remote;

        }

        public IBinder asBinder()

        {

            return mRemote;

        }

        public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,

                String resolvedType, IBinder resultTo, String resultWho, int requestCode,

                int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {

            Parcel data = Parcel.obtain();

            Parcel reply = Parcel.obtain();

            data.writeInterfaceToken(IActivityManager.descriptor);

            data.writeStrongBinder(caller != null ? caller.asBinder() : null);

            data.writeString(callingPackage);

            intent.writeToParcel(data, 0);

            data.writeString(resolvedType);

            data.writeStrongBinder(resultTo);

            data.writeString(resultWho);

            data.writeInt(requestCode);

            data.writeInt(startFlags);

            if (profilerInfo != null) {

                data.writeInt(1);

                profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);

            } else {

                data.writeInt(0);

            }

            if (options != null) {

                data.writeInt(1);

                options.writeToParcel(data, 0);

            } else {

                data.writeInt(0);

            }

            mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);

            reply.readException();

            int result = reply.readInt();

            reply.recycle();

            data.recycle();

            return result;

        }

    可以看到asInterface返回了一个ActivityManagerProxy对象,也就是说ActivityManagerNative.getDefault()返回的就是一个ActivityManagerProxy对象,通过之前的BInder机制的文章我们可以知道Proxy是运行在客户端的,客户端通过将参数写入Proxy类,接着Proxy就会通过Binder去远程调用服务端的具体方法,因此,我们只是借用ActivityManagerProxy来调用ActivityManagerService的方法ActivityManagerService继承自ActivityManagerNative,而ActivityManagerNative继承自Binder并实现了IActivityManager这个Binder接口,因此ActivityManagerService也是一个Binder,并且是IActivityManager的具体实现。

    接着看看在AMS中启动Activity,源码如下:

        @Override

        public final int startActivity(IApplicationThread caller, String callingPackage,

                Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,

                int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {

            return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,

                    resultWho, requestCode, startFlags, profilerInfo, bOptions,

                    UserHandle.getCallingUserId());

        }

        @Override

        public final int startActivityAsUser(IApplicationThread caller, String callingPackage,

                Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,

                int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {

            enforceNotIsolatedCaller("startActivity");

            userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),

                    userId, false, ALLOW_FULL_ONLY, "startActivity", null);

            // TODO: Switch to user app stacks here.

            return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,

                    resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,

                    profilerInfo, null, null, bOptions, false, userId, null, null);

        }

    在startActivity中直接调用了startActivityAsUser方法,而在startActivityAsUser中则是调用mStackSupervisor.startActivityMayWait方法。

    startActivityMayWait函数源码较长,简单总结起来流程如下: 

    startActivityMayWait()->startActivityLocked()->startActivityUncheckedLocked()->startSpecificActivityLocked()->startActivityLocked()->resumeTopActivitiesLocked()->resumeTopActivityLocked()。

    经过一系列的调用之后,最终来到了startPausingLocked方法,它会执行Activity的onPause方法,从而结束当前的Activity。

    final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping, boolean resuming,boolean dontWait) {

        ...

        if (prev.app != null && prev.app.thread != null) {

            if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueueing pending pause: " + prev);

            try {

                EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,

                        prev.userId, System.identityHashCode(prev),

                        prev.shortComponentName);

                mService.updateUsageStats(prev, false);

                prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,

                        userLeaving, prev.configChangeFlags, dontWait);

            } catch (Exception e) {

                // Ignore exception, if process died other code will cleanup.

                Slog.w(TAG, "Exception thrown during pause", e);

                mPausingActivity = null;

                mLastPausedActivity = null;

                mLastNoHistoryActivity = null;

            }

        } else {

            mPausingActivity = null;

            mLastPausedActivity = null;

            mLastNoHistoryActivity = null;

        }

        ...

    }

    这段代码非常重要,因为app.thread的类型为IApplicationThread,它的具体实现是ActivityThread中的ApplicationThread类,而ApplicationThread则是ActivityThread的一个内部类,它继承了IApplicationThread,并且都是Binder对象,所以说Appcation是一个客户端,而ActivityThread是一个服务端,到现在为止,Activity的调用来到了ActivityThread中。

    在ActivityThread中pause掉当前Activity,是调用了schedulePauseActivity来执行pause操作:

    public final void schedulePauseActivity(IBinder token, boolean finished,

                    boolean userLeaving, int configChanges, boolean dontReport) {

                int seq = getLifecycleSeq();

                if (DEBUG_ORDER) Slog.d(TAG, "pauseActivity " + ActivityThread.this

                        + " operation received seq: " + seq);

                sendMessage(

                        finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,

                        token,

                        (userLeaving ? USER_LEAVING : 0) | (dontReport ? DONT_REPORT : 0),

                        configChanges,

                        seq);

            }

    可以看到在schedulePauseActivity中则是通过handler来发送消息,消息类型为PAUSE_ACTIVITY_FINISHING

      private void handlePauseActivity(IBinder token, boolean finished,

                boolean userLeaving, int configChanges, boolean dontReport, int seq) {

            ActivityClientRecord r = mActivities.get(token);

            if (DEBUG_ORDER) Slog.d(TAG, "handlePauseActivity " + r + ", seq: " + seq);

            if (!checkAndUpdateLifecycleSeq(seq, r, "pauseActivity")) {

                return;

            }

            if (r != null) {

                //Slog.v(TAG, "userLeaving=" + userLeaving + " handling pause of " + r);

                if (userLeaving) {

                    performUserLeavingActivity(r);

                }

                r.activity.mConfigChangeFlags |= configChanges;

                performPauseActivity(token, finished, r.isPreHoneycomb(), "handlePauseActivity");

                // 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) {

                        throw ex.rethrowFromSystemServer();

                    }

                }

                mSomeActivitiesChanged = true;

            }

        }

    启动新的Activity, 在startSpecificActivityLocked方法中,其实现细节则是和调用Activity的pause方法一样,都是通过Handler机制,发送一个启动Activity的消息,接着处理该消息最后启动Activity。其调用的是performLaunchActivity方法:

    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {

            // System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");

            ActivityInfo aInfo = r.activityInfo;

            if (r.packageInfo == null) {

                r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,

                        Context.CONTEXT_INCLUDE_CODE);

            }

            ComponentName component = r.intent.getComponent();

            if (component == null) {

                component = r.intent.resolveActivity(

                    mInitialApplication.getPackageManager());

                r.intent.setComponent(component);

            }

            if (r.activityInfo.targetActivity != null) {

                component = new ComponentName(r.activityInfo.packageName,

                        r.activityInfo.targetActivity);

            }

            Activity activity = null;

            try {

                java.lang.ClassLoader cl = r.packageInfo.getClassLoader();

                activity = mInstrumentation.newActivity(

                        cl, component.getClassName(), r.intent);

                StrictMode.incrementExpectedActivityCount(activity.getClass());

                r.intent.setExtrasClassLoader(cl);

                r.intent.prepareToEnterProcess();

                if (r.state != null) {

                    r.state.setClassLoader(cl);

                }

            } catch (Exception e) {

                if (!mInstrumentation.onException(activity, e)) {

                    throw new RuntimeException(

                        "Unable to instantiate activity " + component

                        + ": " + e.toString(), e);

                }

            }

            try {

                Application app = r.packageInfo.makeApplication(false, mInstrumentation);

                if (localLOGV) Slog.v(TAG, "Performing launch of " + r);

                if (localLOGV) Slog.v(

                        TAG, r + ": app=" + app

                        + ", appName=" + app.getPackageName()

                        + ", pkg=" + r.packageInfo.getPackageName()

                        + ", comp=" + r.intent.getComponent().toShortString()

                        + ", dir=" + r.packageInfo.getAppDir());

                if (activity != null) {

                    Context appContext = createBaseContextForActivity(r, activity);

                    CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());

                    Configuration config = new Configuration(mCompatConfiguration);

                    if (r.overrideConfig != null) {

                        config.updateFrom(r.overrideConfig);

                    }

                    if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "

                            + r.activityInfo.name + " with config " + config);

                    Window window = null;

                    if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {

                        window = r.mPendingRemoveWindow;

                        r.mPendingRemoveWindow = null;

                        r.mPendingRemoveWindowManager = null;

                    }

                    activity.attach(appContext, this, getInstrumentation(), r.token,

                            r.ident, app, r.intent, r.activityInfo, title, r.parent,

                            r.embeddedID, r.lastNonConfigurationInstances, config,

                            r.referrer, r.voiceInteractor, window);

                    if (customIntent != null) {

                        activity.mIntent = customIntent;

                    }

                    r.lastNonConfigurationInstances = null;

                    activity.mStartedActivity = false;

                    int theme = r.activityInfo.getThemeResource();

                    if (theme != 0) {

                        activity.setTheme(theme);

                    }

                    activity.mCalled = false;

                    if (r.isPersistable()) {

                        mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);

                    } else {

                        mInstrumentation.callActivityOnCreate(activity, r.state);

                    }

                    if (!activity.mCalled) {

                        throw new SuperNotCalledException(

                            "Activity " + r.intent.getComponent().toShortString() +

                            " did not call through to super.onCreate()");

                    }

                    r.activity = activity;

                    r.stopped = true;

                    if (!r.activity.mFinished) {

                        activity.performStart();

                        r.stopped = false;

                    }

                    if (!r.activity.mFinished) {

                        if (r.isPersistable()) {

                            if (r.state != null || r.persistentState != null) {

                                mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,

                                        r.persistentState);

                            }

                        } else if (r.state != null) {

                            mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);

                        }

                    }

                    if (!r.activity.mFinished) {

                        activity.mCalled = false;

                        if (r.isPersistable()) {

                            mInstrumentation.callActivityOnPostCreate(activity, r.state,

                                    r.persistentState);

                        } else {

                            mInstrumentation.callActivityOnPostCreate(activity, r.state);

                        }

                        if (!activity.mCalled) {

                            throw new SuperNotCalledException(

                                "Activity " + r.intent.getComponent().toShortString() +

                                " did not call through to super.onPostCreate()");

                        }

                    }

                }

                r.paused = true;

                mActivities.put(r.token, r);

            } catch (SuperNotCalledException e) {

                throw e;

            } catch (Exception e) {

                if (!mInstrumentation.onException(activity, e)) {

                    throw new RuntimeException(

                        "Unable to start activity " + component

                        + ": " + e.toString(), e);

                }

            }

            return activity;

        }

    可以看到最终的Activity对象终于创建出来了。

    参考《Android开发艺术探索》作者博客

    相关文章

      网友评论

          本文标题:从源码的角度描述Activity的启动过程

          本文链接:https://www.haomeiwen.com/subject/vqethftx.html