四大组件之Activity(三)- 任务栈

原创文章,转载注明出处。

任务栈管理是Activity中非常重要的一部分,这篇文章来学习下。代码继续使用的Android9.0源码.

一、关键类介绍

Activity任务栈主要牵涉到如下几个重要类:

ActivityRecord: Activity对应的实体对象;

TaskRecord:Activity任务栈,一个或多个ActivityRecord组成TaskRecord;

ActivityStack:不是真正的Activity栈,他是TaskRecord管理类,一个或多个TaskRecord组成ActivityStack;

ActivityStackSupervisor:ActivityStack的管理类。

在Android系统中,每个应用都有自己的Activity任务栈和内部对应的Activity,但是应用本身不会去管理他们,而且将Activity封装成ActivityRecord对象,丢给系统,交由系统来管理。

ActivityRecord

final class ActivityRecord {
   ProcessRecord app //跑在哪个进程
   TaskRecord task //跑在哪个task
   ActivityInfo info // Activity信息
   int mActivityType //Activity类型
   ActivityState state //Activity状态
   ApplicationInfo appInfo //跑在哪个app
   ComponentName realActivity //组件名
   String packageName //包名
   String processName //进程名
   int launchMode //启动模式
   int userId // 该Activity运行在哪个用户id
  …
}

以上信息,主要包含用户组,进程、Task、包信息、以及Activity自身状态和信息。

TaskRecord

final class TaskRecord {
   ActivityStack stack; //当前所属的stack
   final ArrayList mActivities;// 当前task的所有Activity列表
   final int taskId  
   String affinity;// 是指root activity的affinity,即该Task中第一个Activity;
   int mCallingUid;
   String mCallingPackage; //调用者的包名
   ...
}

对ActivityRecord的管理主要是通过对mActivities集合的增删改查的操作来实现。

一个应用程序都有可能不止一个任务栈,那么对应真个系统来说,肯定是需要针对多个ActivityRecord进行统一的管理,那么这个类就叫ActivityStack,从名字上看很容易误以为它才是任务栈,其实不然。

final class ActivityStack {
   ArrayList mTaskHistory //保存所有的Task列表
   ArrayList mStacks; //所有stack列表
   final int mStackId;
   int mDisplayId;
   final ArrayList mLRUActivities = new ArrayList<>(); //按LRU排列的Activity
   final ArrayList mNoAnimActivities = new ArrayList<>();//没有转场动画的Activity
   ActivityRecord mPausingActivity //正在pause的Activity
   ActivityRecord mLastPausedActivity //最后pause的Activity
   ActivityRecord mResumedActivity //已经resumed的Activity
   ActivityRecord mLastStartedActivity//最后resumed的Activity
  ...
   enum ActivityState { //Activity的各种生命周期状态
      INITIALIZING,
      RESUMED,
      PAUSING,
      PAUSED,
      STOPPING,
      STOPPED,
      FINISHING,
      DESTROYING,
      DESTROYED
   }
 ...
}

从对象属性来看,首当其冲的还是TaskRecord集合,它是所有Task的集合, 具体方法也是针对mTaskHistory来进行增删改查操作。除此以外,它的内部还维护了mLRUActivities 和 mNoAnimActivities 这样的针对ActivityRecord的特殊集合,同时保存着对应Activity生命周期状态和对象。总体来看就是ActivityRecord 和 TaskRecord一把抓。

ActivityStackSupervisor是ActivityStack的管理类,但是实际上是由ActivityDisplay来统一管理的。

ActivityStackSupervisor在AMS构造方法中被初始化,对于没有分屏功能以及虚拟屏的情况下,ActivityStackSupervisor和ActivityDisplay是系统唯一的。

ActivityStackSupervisor

public final class ActivityStackSupervisor implements DisplayListener {
   ActivityStack mHomeStack //桌面的stack(Launcher app Stack)
   ActivityStack mFocusedStack //当前聚焦stack(App Stack)
   …
}

mStacks集合保存所有ActivityStack。

ActivityDisplay

class ActivityDisplay extends ConfigurationContainer
        implements WindowContainerListener {
 …
 private final ArrayList mStacks = new ArrayList<>();
  …
 private ActivityStack mHomeStack = null;
 private ActivityStack mRecentsStack = null;
 private ActivityStack mPinnedStack = null;
 private ActivityStack mSplitScreenPrimaryStack = null;
 …
}

以上对象之间的关系如下图所示:

四大组件之Activity(三)- 任务栈_第1张图片
二、从Activity启动流程来看任务栈管理

Activity启动过程中,start、pause、stop Activity都是先通过 应用 Binder IPC到 AMS,然后AMS 通知相关任务栈管理类进行任务栈调整,最后Binder IPC到应用,通过消息泵来分发对应生命周期的处理。那么这里我们看下startActivity中 AMS到ApplicationThread 中间任务栈工作部分来简单了解下整个任务栈的管理。代码基于android 9.0 。

先看一个整体流程图:

四大组件之Activity(三)- 任务栈_第2张图片

图用的是刘皇叔的,大流程上9.0依然是如此,只是代码处理细节有些许调整,直接借图了。

AMS先执行startActivity

5078    @Override
5079    public final int startActivity(IApplicationThread caller, String callingPackage,
5080            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
5081            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
5082        return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
5083                resultWho, requestCode, startFlags, profilerInfo, bOptions,
5084                UserHandle.getCallingUserId());
5085    }

这里没什么好讲的,直接调用startActivityAsUser。

startActivityAsUser有多个重载,最终执行:

5096    public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
5097            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
5098            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId,
5099            boolean validateIncomingUser) {
5100        enforceNotIsolatedCaller("startActivity");
5101
5102        userId = mActivityStartController.checkTargetUser(userId, validateIncomingUser,
5103                Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");
5104
5105        // TODO: Switch to user app stacks here.
5106        return mActivityStartController.obtainStarter(intent, "startActivityAsUser")
5107                .setCaller(caller)
5108                .setCallingPackage(callingPackage)
5109                .setResolvedType(resolvedType)
5110                .setResultTo(resultTo)
5111                .setResultWho(resultWho)
5112                .setRequestCode(requestCode)
5113                .setStartFlags(startFlags)
5114                .setProfilerInfo(profilerInfo)
5115                .setActivityOptions(bOptions)
5116                .setMayWait(userId)
5117                .execute();
5118
5119    }

这里使用了建造者模式,通过ActivityStartController构造了ActivityStarter,Activity启动管理类.其中.setMayWait(userId)的方法内部会走mRequest.mayWait = true;

继续
ActivityStarter #execute

481    int execute() {
482        try {
483            // TODO(b/64750076): Look into passing request directly to these methods to allow
484            // for transactional diffs and preprocessing.
485            if (mRequest.mayWait) { //true
486                return startActivityMayWait(mRequest.caller, mRequest.callingUid,
487                        mRequest.callingPackage, mRequest.intent, mRequest.resolvedType,
488                        mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
489                        mRequest.resultWho, mRequest.requestCode, mRequest.startFlags,
490                        mRequest.profilerInfo, mRequest.waitResult, mRequest.globalConfig,
491                        mRequest.activityOptions, mRequest.ignoreTargetSecurity, mRequest.userId,
492                        mRequest.inTask, mRequest.reason,
493                        mRequest.allowPendingRemoteAnimationRegistryLookup);
494            } else {
495                return startActivity(mRequest.caller, mRequest.intent, mRequest.ephemeralIntent,
496                        mRequest.resolvedType, mRequest.activityInfo, mRequest.resolveInfo,
497                        mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
498                        mRequest.resultWho, mRequest.requestCode, mRequest.callingPid,
499                        mRequest.callingUid, mRequest.callingPackage, mRequest.realCallingPid,
500                        mRequest.realCallingUid, mRequest.startFlags, mRequest.activityOptions,
501                        mRequest.ignoreTargetSecurity, [mRequest.componentSpecified](http://mrequest.componentspecified/),
502                        mRequest.outActivity, mRequest.inTask, mRequest.reason,
503                        mRequest.allowPendingRemoteAnimationRegistryLookup);
504            }
505        } finally {
506            onExecutionComplete();
507        }
508    }

从前面mRequest.mayWait = true 可以知道这里会执行startActivityMayWait

ActivityStarter #startActivityMayWait

945    private int startActivityMayWait(IApplicationThread caller, int callingUid,
946            String callingPackage, Intent intent, String resolvedType,
947            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
948            IBinder resultTo, String resultWho, int requestCode, int startFlags,
949            ProfilerInfo profilerInfo, WaitResult outResult,
950            Configuration globalConfig, SafeActivityOptions options, boolean ignoreTargetSecurity,
951            int userId, TaskRecord inTask, String reason,
952            boolean allowPendingRemoteAnimationRegistryLookup) {
                   …
                  ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
                    ...
                  // Collect information about the target of the Intent.
                  ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
                    …
1099            int res = startActivity(caller, intent, ephemeralIntent, resolvedType, aInfo, rInfo,
1100                    voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid,
1101                    callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options,
1102                    ignoreTargetSecurity, componentSpecified, outRecord, inTask, reason,
1103                    allowPendingRemoteAnimationRegistryLookup);
          ...
1174    }

这个过程,收集了若干启动参数信息,包括intent、ActivityInfo、CallingPid、CallingUid、package信息以及startFlag等信息,之后传参给startActivity做处理, 如果mRequest.mayWait 为false,那么就省了startActivityMayWait,直接执行startActivity。至于false的场景暂时先不讨论,有兴趣可以自己追一下代码.

ActivityStarter #startActivity

528    private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
529            String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
530            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
531            IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
532            String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
533            SafeActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
534            ActivityRecord[] outActivity, TaskRecord inTask, String reason,
535            boolean allowPendingRemoteAnimationRegistryLookup) {
536
537        if (TextUtils.isEmpty(reason)) {
538            throw new IllegalArgumentException("Need to specify a reason.");
539        }
540        mLastStartReason = reason; //获取启动原因
541        mLastStartActivityTimeMs = System.currentTimeMillis(); //获取启动时间
542        mLastStartActivityRecord[0] = null;
543        //这里又调用了一个startActivity
544        mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType,
545                aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode,
546                callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
547                options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord,
548                inTask, allowPendingRemoteAnimationRegistryLookup);
549
550        if (outActivity != null) {
551            // mLastStartActivityRecord[0] is set in the call to startActivity above.
552            outActivity[0] = mLastStartActivityRecord[0];
553        }
554
555        return getExternalResult(mLastStartActivityResult);
556    }

这个方法内部做的事情不多,简单地获取了取启动原因和时间,然后又调用了一个重载方法。

接着看:

571    private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
572            String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
573            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
574            IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
575            String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
576            SafeActivityOptions options,
577            boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity,
578            TaskRecord inTask, boolean allowPendingRemoteAnimationRegistryLookup) {
579        int err = ActivityManager.START_SUCCESS;
580        // Pull the optional Ephemeral Installer-only bundle out of the options early.
581        final Bundle verificationBundle
582                = options != null ? options.popAppVerificationBundle() : null;
583        获取调用者进程记录对象
584        ProcessRecord callerApp = null;
585        if (caller != null) {
586            callerApp = mService.getRecordForAppLocked(caller);
587            if (callerApp != null) {
588                callingPid = callerApp.pid;
589                callingUid = callerApp.info.uid;
590            } else {
591                Slog.w(TAG, "Unable to find app for caller " + caller
592                        + " (pid=" + callingPid + ") when starting: "
593                        + intent.toString());
594                err = ActivityManager.START_PERMISSION_DENIED;
595            }
596        }
             ...
606        ActivityRecord sourceRecord = null;
607        ActivityRecord resultRecord = null;
608        if (resultTo != null) {
                 //获取调用者所在的Activity
609            sourceRecord = mSupervisor.isInAnyStackLocked(resultTo);
610            if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
611                    "Will send result to " + resultTo + " " + sourceRecord);
612            if (sourceRecord != null) {
613                if (requestCode >= 0 && !sourceRecord.finishing) {
614                    resultRecord = sourceRecord;
615                }
616            }
617        }
618
             ...//一系列问题的检查 。包括Activity、Intent、Class、Permission等,同时对多种error的情况做了判断
706        final ActivityStack resultStack = resultRecord == null ? null : resultRecord.getStack();
            ...
            //创建Activity的实体类
826        ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
827                callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
828                resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
829                mSupervisor, checkedOptions, sourceRecord);
830        if (outActivity != null) {
831            outActivity[0] = r;
832        }
             …
             //当前stack 成为focusedStack
840        final ActivityStack stack = mSupervisor.mFocusedStack;
841
842        // If we are starting an activity that is not from the same uid as the currently resumed
843        // one, check whether app switches are allowed.
844        if (voiceSession == null && (stack.getResumedActivity() == null
845                || stack.getResumedActivity().info.applicationInfo.uid != realCallingUid)) {
                 // 前台stack还没有resume状态的Activity时, 则检查app切换是否允许
846            if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
847                    realCallingPid, realCallingUid, "Activity start")) {
                // 当不允许切换,则把要启动的Activity添加到mPendingActivityLaunches对象, 并且直接返回.
848                mController.addPendingActivityLaunch(new PendingActivityLaunch(r,
849                        sourceRecord, startFlags, stack, callerApp));
850                ActivityOptions.abort(checkedOptions);
851                return ActivityManager.START_SWITCHES_CANCELED;
852            }
853        }
            ...
866        mController.doPendingActivityLaunches(false);
867
868        return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
869                true /* doResume */, checkedOptions, inTask, outActivity);
870    }

这个过程代码不少,整体来说,前面收集了一大把信息,在这里就派上用场了,简单说就是确认了调用进程、也通过PMS确认了要调用的Activity,并对一些列信息包括Activity、Intent、Class、Permission进行检查以及多重if else的error判断。如果满足条件,则封装成ActivityRecord。继续执行startActivity(又是startActivity...)。

1193    private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
1194                IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
1195                int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
1196                ActivityRecord[] outActivity) {
1197        int result = START_CANCELED;
1198        try {
1199            mService.mWindowManager.deferSurfaceLayout();
1200            result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
1201                    startFlags, doResume, options, inTask, outActivity);
1202        } finally {
1203            // If we are not able to proceed, disassociate the activity from the task. Leaving an
1204            // activity in an incomplete state can lead to issues, such as performing operations
1205            // without a window container.
1206            final ActivityStack stack = mStartActivity.getStack();
1207            if (!ActivityManager.isStartResultSuccessful(result) && stack != null) {
1208                stack.finishActivityLocked(mStartActivity, RESULT_CANCELED,
1209                        null /* intentResultData */, "startActivity", true /* oomAdj */);
1210            }
1211            mService.mWindowManager.continueSurfaceLayout();
1212        }
1213
1214        postStartActivityProcessing(r, result, mTargetStack);
1215
1216        return result;
1217    }

这里没太多内容,主要是执行了 startActivityUnchecked,我们先看这个方法

ActivityStarter # startActivityUnchecked

1220    private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
1221            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
1222            int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
1223            ActivityRecord[] outActivity) {
1225        setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
1226                voiceInteractor); //把方法参数赋值给ActivityStarter成员变量。
1227        //通过方法参数先明确一下:ActivityRecord r 为本次要启动的Activity,ActivityRecord sourceRecord为调用者Activity
1228        computeLaunchingTaskFlags(); //对启动模式进行检查与LaunchFlags赋值
1229      
1230        computeSourceStack();
1231
1232        mIntent.setFlags(mLaunchFlags); //把计算好的LaunchFlags 给Intent
                mReusedActivity = getReusableIntentActivity();//本次要调用的Activity在已存在的Task中则返回mReusedActivity
            ...//根据LaunchFlags 与启动模式 来调整被调用Activity所在的任务栈
            if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
               || mLaunchSingleInstance || mLaunchSingleTask) { //singleTop or SingleInstance的处理
              // In this situation we want to remove all activities from the task up to the one
              // being started. In most cases this means we are resetting the task to its initial
              // state.
              final ActivityRecord top = mReusedActivity.task.performClearTaskForReuseLocked(
              mStartActivity, mLaunchFlags);
        if (top != null) {
            if (top.frontOfTask) {
                // Activity aliases may mean we use different intents for the top activity,
                // so make sure the task now has the identity of the new intent.
                top.task.setIntent(mStartActivity);
           }
            ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.task);
             top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
                      mStartActivity.launchedFromPackage);
            }
                }
          ...
1408        if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
1409                && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) { //根启动Activity是使用 FLAG_ACTIVITY_NEW_TASK
1410            newTask = true;
                   //创建新的TaskRecord
1411            result = setTaskFromReuseOrCreateNewTask(taskToAffiliate, topStack);
1412        }
             ...
1466            mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
1467                        mOptions);
1468            }
            ...
1477        return START_SUCCESS;
1478    }

startActivityUnchecked方法主要是根据LaunchFlags 与启动模式 来调整被调用Activity所在的任务栈

根Activity对应的flag是FLAG_ACTIVITY_NEW_TASK,则创建新的TaskRecord ,并执行mSupervisor.resumeFocusedStackTopActivityLocked。

ActivityStackSupervisor#resumeFocusedStackTopActivityLocked

2214    boolean resumeFocusedStackTopActivityLocked(
2215            ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
2216
2217        if (!readyToResume()) {
2218            return false;
2219        }
2220        
2221        if (targetStack != null && isFocusedStack(targetStack)) {
2222            return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
2223        }
2224
2225        final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
2226        if (r == null || !r.isState(RESUMED)) {
2227            mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
2228        } else if (r.isState(RESUMED)) {
2229            // Kick off any lingering app transitions form the MoveTaskToFront operation.
2230            mFocusedStack.executeAppTransition(targetOptions);
2231        }
2232
2233        return false;
2234    }
//当前Activity所在stack是focusedStack,或者当前focusedStack的栈顶活动的activity为空或者不是resume状态
那么执行resumeTopActivityUncheckedLocked
ActivityStack#resumeTopActivityUncheckedLocked
2282    boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
2283        if (mStackSupervisor.inResumeTopActivity) {
2284            // Don't even start recursing.
2285            return false;
2286        }
2287
2288        boolean result = false;
2289        try {
2290            // Protect against recursion.
2291            mStackSupervisor.inResumeTopActivity = true;
2292            result = resumeTopActivityInnerLocked(prev, options);
2301            final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);
2302            if (next == null || !next.canTurnScreenOn()) {
2303                checkReadyForSleep();
2304            }
2305        } finally {
2306            mStackSupervisor.inResumeTopActivity = false;
2307        }
2308
2309        return result;
2310    }

再看ActivityStack#resumeTopActivityInnerLocked

2330    private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
            …
            //当前存在其他的Activity处于Resume状态,那么会走 startPausingLocked。
2442        if (mResumedActivity != null) {
                //主要是通知ActivityThread执行schedulePause流程
2445            pausing |= startPausingLocked(userLeaving, false, next, false);
2446        }
            …
                    //最终都会调用到这
2754            mStackSupervisor.startSpecificActivityLocked(next, true, true);
2755  
2758        return true;
2759    }
1678    void startSpecificActivityLocked(ActivityRecord r,
1679            boolean andResume, boolean checkConfig) {
1680        //获取对应进程
1681        ProcessRecord app = mService.getProcessRecordLocked(r.processName,
1682                r.info.applicationInfo.uid, true);
1683
1684        getLaunchTimeTracker().setLaunchTime(r);
1685
1686        if (app != null && app.thread != null) {
1687            try {
1688                if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
1689                        || !"android".equals(r.info.packageName)) {
1694                    app.addPackage(r.info.packageName, r.info.applicationInfo.longVersionCode,
1695                            mService.mProcessStats);
1696                }
                       //如果进程存在,则执行scheduleLauncherActivity流程
1697                realStartActivityLocked(r, app, andResume, checkConfig);
1698                return;
1699            } catch (RemoteException e) {
1700                Slog.w(TAG, "Exception when starting activity "
1701                        + r.intent.getComponent().flattenToShortString(), e);
1702            }
1703
1704            // If a dead object exception was thrown -- fall through to
1705            // restart the application.
1706        }
1707        //如果进程不存在,则执行进程创建流程
1708        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
1709                "activity", r.intent.getComponent(), false, false, true);
1710    }

简单总结:

  1. startActivity首先会收集启动数据,经过验证如果满足条件,则会创建一个ActivityRecord。
  2. 根据flag 与启动模式 调整任务栈。
  3. 之前如果已经存在其他的Resume状态的Activity,那么需要先让它pause。
  4. 最后看所在进程是否存在,如果不存在则还需要走进程启动流程。
三、启动模式
  • standard(默认) :启动一个新Activity就加入栈顶,不考虑重复。
  • singleTop :栈顶复用。
  • singleTask :栈内复用,且之上的所有Activity统统出栈。
  • singleInstance :独享栈。
四、任务栈两种主要设置操作
  • 同一个程序不同activity放入不同的栈中:为不同的activity设置不同的taskaffnity属性,启动activity的Intent需要包含FLAG_ACTIVITY_NEW_TASK标记。

  • 不同程序的activity放入同一个栈中:activity 标签中加入: android:allowTaskReparenting=“true” 和 android:taskAffinity=“same label”。

一个小demo演示下, 代码很简单就两个Activity,点击click跳转:

不做任何设置,同一app中不同activity在相同task中。

   Running activities (most recent first):
      TaskRecord{707a762 #1205 A=com.stan.appmodule U=0 StackId=1 sz=2}
        Run #1: ActivityRecord{6864c55 u0 com.stan.appmodule/.BActivity t1205}
        Run #0: ActivityRecord{eb6d3fa u0 com.stan.appmodule/.MainActivity t1205}

为不同的activity设置不同的taskaffnity属性,启动activity的Intent需要包含FLAG_ACTIVITY_NEW_TASK标记。

    Running activities (most recent first):
      TaskRecord{1a2b940 #1209 A=com.stan.appmodule.BActivity U=0 StackId=1 sz=1}
        Run #1: ActivityRecord{d80b33c u0 com.stan.appmodule/.BActivity t1209}
      TaskRecord{e3a9079 #1208 A=com.stan.appmodule.MainActivity U=0 StackId=1 sz=1}
        Run #0: ActivityRecord{d369326 u0 com.stan.appmodule/.MainActivity t1208}

不同程序的activity放入同一个栈中:activity 标签中加入: android:allowTaskReparenting=“true” 和 android:taskAffinity=“same label”。

两个app: com.stan.appmodule 和 com.stan.appmodule2 ,对两者的MainActivity设置如上属性

    Running activities (most recent first):
      TaskRecord{5a7f1be #1210 A=com.stan.appmodule.MainActivity U=0 StackId=1 sz=2}
        Run #1: ActivityRecord{9c70786 u0 com.stan.appmodule2/.MainActivity t1210}
        Run #0: ActivityRecord{e989b91 u0 com.stan.appmodule/.MainActivity t1210}

你可能感兴趣的:(四大组件之Activity(三)- 任务栈)