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

从源码的角度描述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开发艺术探索》作者博客

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 193,968评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,682评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,254评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,074评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,964评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,055评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,484评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,170评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,433评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,512评论 2 308
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,296评论 1 325
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,184评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,545评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,150评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,437评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,630评论 2 335

推荐阅读更多精彩内容