Activity启动流程

Activity启动流程


一、执行startActivity

  • Activity.startActivity(Intent intent, @Nullable Bundle options)

    @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);
        }
    }
    
  • Activity.startActivityForResult ------requestCode == -1

    mInstrumentation.execStartActivity(
        this, mMainThread.getApplicationThread(), mToken, this,
        intent, requestCode, options);
    

    “Instrumentation是启动Activity的操作类”,每一个应用程序只有一个Instrumentation对象,每个Activity持有一个该对象的引用。包括了调用Activity的各生命周期方法的callActivityxxx()。

  • Instrumentation.execStartActivty

    int result = ActivityManagerNative.getDefault()
                    .startActivity(whoThread, who.getBasePackageName(), intent,
                            intent.resolveTypeIfNeeded(who.getContentResolver()),
                            token, target != null ? target.mEmbeddedID : null,
                            requestCode, 0, null, options);
    

    getDefault()返回的是:

    static public IActivityManager getDefault() {
        return gDefault.get();
    }
    
        private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
            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;
            }
        };
    
    asInterface{
      ....
      return new ActivityManagerProxy(obj);
    }
    

    ActivityManagerNative extends Binder

    接口的实现关系:

    ​ IInterface->IActivityManager–> ActivityManagerNative/ActivityManagerProxy

    ​ ActivityManagerNative作为AMS的客户端通过ActivityManagerProxy向AMS发送启动请求。

    ActivityManagerService extends ActivityManagerNative
    
  • ActivityManagerProxy.startActivity()

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

    通过binder向AMS传输数据,AMS调用startActivity()方法


通过Binder向AMS发送启动Activity请求

二、ActivityManagerService接收启动Activity的请求,并控制前台Activity调用onPause

在AMSstartActivity()方法内部,继续调用startActivityAsUser()方法:

  • ActivityManagerService.startActivity()
@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());
}
  • ActvityiManagerService.startActivityAsUser()

    @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) {
        ....
        return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
                resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
                profilerInfo, null, null, bOptions, false, userId, null, null);
    }
    

    该方法返回时,调用了ActivityStarter.startActivityMayWait()方法。

    • ActivityStarter是一个专门负责Activity启动的控制类,通过intent和flag决定如何启动一个Activity,并关联到Task和Stack。

    ActivityStarter.startActivityMayWait()方法中,返回值如下:

  • ActivityStarter.startActivityMayWait()

    int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
            aInfo, rInfo, voiceSession, voiceInteractor,
            resultTo, resultWho, requestCode, callingPid,
            callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
            options, ignoreTargetSecurity, componentSpecified, outRecord, container,
            inTask);
    .....
    return res;
    

    我们可以看到此处调用了ActivityStarter.startActivityLocked()方法,该方法关键部分如下:

  • ActivityStarter.startActivityLocked()

    mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType,
                    aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode,
                    callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
                    options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord,
                    container, inTask);
    
    ····
    return mLastStartActivityResult;
    

    调用的startActivity()方法:

    ····
    try {
                mService.mWindowManager.deferSurfaceLayout();
                result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,startFlags, doResume, options, inTask, outActivity);
            }
    ····
    return result;;
    

    这里又调用了另一个方法ActivityStarter.startActivityUnchecked(),在该方法中进行了大量逻辑操作,这里挑出部分:

  • ActivityStarter.startActivityUnchecked()

    ····
    final ActivityStack topStack = mSupervisor.mFocusedStack;
    final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
    ····
    

    关于ActivityStackSupervisor,它用来保存Activity的栈信息

    • ActivityStackSupervisor
        /** The stack containing the launcher app. Assumed to always be attached to
         * Display.DEFAULT_DISPLAY. */
        ActivityStack mHomeStack;
    
        /** The stack currently receiving input or launching the next activity. */
        ActivityStack mFocusedStack;
    
        /** If this is the same as mFocusedStack then the activity on the top of the focused stack has
         * been resumed. If stacks are changing position this will hold the old stack until the new
         * stack becomes resumed after which it will be set to mFocusedStack. */
        private ActivityStack mLastFocusedStack;
    

    mHomeStack : 只保存了 Launcher 的 Task;

    mLastFocusedStack: 当该值等于mFocusedStack,代表当前栈顶的Activity完成resume;
    ​ 当该值等于上一个旧栈时,代表activity正在切换;

mIntent.setFlags(mLaunchFlags);//设置启动flag
mReusedActivity = getReusableIntentActivity();//决定是否将新的Activity插入到现有的task
····
final boolean dontStart = top != null && mStartActivity.resultTo == null
                && top.realActivity.equals(mStartActivity.realActivity)
                && top.userId == mStartActivity.userId
                && top.app != null && top.app.thread != null
                && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
                || mLaunchSingleTop || mLaunchSingleTask);
        if (dontStart) {
            ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);
            // For paranoia, make sure we have correctly resumed the top activity.
            topStack.mLastPausedActivity = null;
            if (mDoResume) {
                mSupervisor.resumeFocusedStackTopActivityLocked();
            }
          ·····
            return START_DELIVERED_TO_TOP;
        }
·····
mTargetStack.startActivityLocked(mStartActivity, newTask, mKeepCurTransition, mOptions);//启动Activity、是否开启新task···
····
mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);//更新last used stack ID
····
  • ActivityStack.startActivityLocked()

    ····
    TaskRecord rTask = r.task;
    final int taskId = rTask.taskId;
    // mLaunchTaskBehind tasks get placed at the back of the task stack.
    if (!r.mLaunchTaskBehind && (taskForIdLocked(taskId) == null || newTask)) {
        // Last activity in task had been removed or ActivityManagerService is reusing task.
        // Insert or replace.
        // Might not even be in.
        insertTaskAtTop(rTask, r);
        mWindowManager.moveTaskToTop(taskId);
    }
    TaskRecord task = null;
    if (!newTask) {//如果不是在新的Task中启动,就找出要运行在TaskRecord的对象
        // If starting in an existing task, find where that is...
        boolean startIt = true;
        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
            task = mTaskHistory.get(taskNdx);
            if (task.getTopActivity() == null) {
                // All activities in task are finishing.
                continue;
            }
            if (task == r.task) {
                // Here it is!  Now, if this is not yet visible to the
                // user, then just add it without starting; it will
                // get started when the user navigates back to it.
                if (!startIt) {
                    if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to task "
                            + task, new RuntimeException("here").fillInStackTrace());
                    task.addActivityToTop(r);
                    r.putInHistory();
                    addConfigOverride(r, task);
                    if (VALIDATE_TOKENS) {
                        validateAppTokensLocked();
                    }
                    ActivityOptions.abort(options);
                    return;
                }
                break;
            } else if (task.numFullscreen > 0) {
                startIt = false;
            }
        }
    }
    
    // Place a new activity at top of stack, so it is next to interact
    // with the user.
    
    // If we are not placing the new activity frontmost, we do not want
    // to deliver the onUserLeaving callback to the actual frontmost
    // activity
    ······
    
  • ActivityStackSupervisor.resumeFocusedStackTopActivityLocked()

    boolean resumeFocusedStackTopActivityLocked(
            ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
        if (targetStack != null && isFocusedStack(targetStack)) {
            return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
        }
        final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
        if (r == null || r.state != RESUMED) {
            mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
        }
        return false;
    }
    
  • ActivityStack.resumeTopActivityUncheckedLocked()

    ····
    result = resumeTopActivityInnerLocked(prev, options);
    ····
    return result;
    

    这里主要调用了mSupervisor.resumeFocusedStackTopActivityLocked()方法,该方法继续调用targetStack.resumeTopActivityUncheckedLocked(target, targetOptions),在

    resumeTopActivityUncheckedLocked方法中,继续调用resumeTopActivityInnerLocked(prev, options)并返回。resumeTopActivityInnerLocked方法关键逻辑如下:

  • ActivityStack.resumeTopActivityInnerLocked()

    ····
     /**
       * Current activity that is resumed, or null if there is none.
       */
      ActivityRecord mResumedActivity = null;
    ····
    //找出还没结束的首个ActivityRecord
    ActivityRecord next = topRunningActivityLocked(null);
    ····
    boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, next,             dontWaitForPause);  
    ····
    //启动前需要暂停前一个Activity
    if (mResumedActivity != null) {  
      if (DEBUG_STATES) Slog.d(TAG_STATES,
              "resumeTopActivityLocked: Pausing " + mResumedActivity);
      pausing |= startPausingLocked(userLeaving, false, next, dontWaitForPause);
    }
    

此时,开始进入pause阶段,调用ActivityStack.startPausingLocked()方法,这里截取主要部分:

  • ActivityStack.startPausingLocked()

    final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping, boolean resuming, boolean dontWait) {
       if (mPausingActivity != null) {
           completePauseLocked(false);
       }
       
      .....
      ActivityRecord prev = mResumedActivity;
      ·····
       
       if (prev.app != null && prev.app.thread != null) 
         try {
               mService.updateUsageStats(prev, false);
               prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
                       userLeaving, prev.configChangeFlags, dontWait);
           } catch (Exception e) {
               mPausingActivity = null;
               mLastPausedActivity = null;
               mLastNoHistoryActivity = null;
           }
       } else {
           mPausingActivity = null;
           mLastPausedActivity = null;
           mLastNoHistoryActivity = null;
       }
       
     .....  
    }
    

    这里,prev.app为记录启动Lancher进程的ProcessRecord,prev.app.thread为Lancher进程的远程调用接口IApplicationThead,调用prev.app.thread.schedulePauseActivity,在Lancher进程中消息传

    递,调用ActivityThread.handlePauseActivity(),最终调用ActivityThread.performPauseActivity()暂停指定Activity。

    ActivityThread.schedulePauseActivity()中发送了一个Message,方法如下:

  • ActivityThread.schedulePauseActivity()

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

在handleMessage的PAUSE_ACTIVITY/PAUSE_ACTIVITY_FINISHING case中均调用了handlePauseActivity方法:

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) { //利用ActivityManagerNative通知ActivityThread已经完成pause
                try {
                    ActivityManagerNative.getDefault().activityPaused(token);
                } catch (RemoteException ex) {
                    throw ex.rethrowFromSystemServer();
                }
            }
            mSomeActivitiesChanged = true;
        }
    }

该方法内,调用了performPauseActivityIfNeeded()方法,在该方法中主要执行的是performPauseActivityIfNeeded()方法完成pause,这里我们看一下performPauseActivityIfNeeded方法的具体实现:

private void performPauseActivityIfNeeded(ActivityClientRecord r, String reason) {
    if (r.paused) {
        // You are already paused silly...
        return;
    }

    try {
        r.activity.mCalled = false;
        mInstrumentation.callActivityOnPause(r.activity);
        EventLog.writeEvent(LOG_AM_ON_PAUSE_CALLED, UserHandle.myUserId(),
                r.activity.getComponentName().getClassName(), reason);
        if (!r.activity.mCalled) {
            throw new SuperNotCalledException("Activity " + safeToComponentShortString(r.intent)
                    + " did not call through to super.onPause()");
        }
    } catch (SuperNotCalledException e) {
        throw e;
    } catch (Exception e) {
        if (!mInstrumentation.onException(r.activity, e)) {
            throw new RuntimeException("Unable to pause activity "
                    + safeToComponentShortString(r.intent) + ": " + e.toString(), e);
        }
    }
    r.paused = true;
}

该方法中,主要调用了mInstrumentation.callActivityOnPause(r.activity) 来执行目标Activity的onPause方法。前面已经说过,“Instrumentation是启动Activity的操作类”,它的callActivityOnPause()如下,Activity.performPause()方法中我们可以看到的确调用了onPause()方法。

/**
 * Perform calling of an activity's {@link Activity#onPause} method.  The
 * default implementation simply calls through to that method.
 * 
 * @param activity The activity being paused.
 */
public void callActivityOnPause(Activity activity) {
    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;
}

以上完成了执行onPause的过程,然后在handlePauseActivity()方法中,继续调用ActivityManagerNative.getDefault().activityPaused()方法,向AMS通知onPause过程已完成。

ActivityThread中schedulePauseActivity()发送Message后,处理消息逻辑整理如下:

handlePauseActivity-performPauseActivity-performPauseActivityIfNeeded  //具体执行目标             |                                                             Activity的onpause方法
ActivityManagerNative
        |
        |—>ActivityMangerProxy—>activityPaused    //ActivityMangerProxy通知ActivityThread
                                    |
                                    |—>AMS

ActivityManagerProxy.activityPaused()

public void activityPaused(IBinder token) throws RemoteException
{
    Parcel data = Parcel.obtain();
    Parcel reply = Parcel.obtain();
    data.writeInterfaceToken(IActivityManager.descriptor);
    data.writeStrongBinder(token);
    mRemote.transact(ACTIVITY_PAUSED_TRANSACTION, data, reply, 0);
    reply.readException();
    data.recycle();
    reply.recycle();
}

ActivityManagerService接收到应用进程创建Activity的请求之后会执行初始化操作,解析启动模式,处理信息等一系列操作。ActivityManagerService保存完请求信息之后会将当前系统栈顶的Activity执行onPause操作。

AMS.activityPaused

@Override
public final void activityPaused(IBinder token) {
    final long origId = Binder.clearCallingIdentity();
    synchronized(this) {
        ActivityStack stack = ActivityRecord.getStackLocked(token);//获取的当前Activity的task的所在栈
        if (stack != null) {
            stack.activityPausedLocked(token, false);
        }
    }
    Binder.restoreCallingIdentity(origId);
}

ActivityStack.activityPausedLocked

if (mPausingActivity == r) {
    if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to PAUSED: " + r
            + (timeout ? " (due to timeout)" : " (pause complete)"));
    completePauseLocked(true, null);
    return;
}
  • Question:

3.任务栈由谁管理,存放在什么地方?

4.启动一个activity都是在主线程中执行的吗?

5.AMS什么时候介入工作的?

6.Binder客户端是怎么和服务端通信的?

7.asinterface含义是什么?

8.整个过程由哪些成员协助完成?

9.他们都起到什么作用?

10.如何图解全过程?

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念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

推荐阅读更多精彩内容