Activity启动模式

处理启动模式的方法的是StackAcivity的代理类StackActivitySupervisor里的startActivityUncheckedLocked.
前面主要是根据Flag来判断需不需要addTask.
当New_Task_Flag时, 且instask, resultTo为null, 除了single instance都会去taskHistory去找ActivityRecord。singleInstance 例子最后再说。当找到时就会尝试着将r (这次要启动的activity)放进去,或者resumeTask里的Activity。
这里讲解下ActivityStack里的找ActivityRecord的findTaskLocked方法:

task.rootAffinity.equals(target.taskAffinity)
  • 默认情况下,一个应用中的所有activity具有相同的taskAffinity,即应用程序的包名。所以这里用affinity作为判断条件来判别是否为想要的
taskIntent.getComponent().compareTo(cls)==0 && Objects.equals(documentData,taskDocumentData)
  • 第二个匹配下 component(调用java compareTo 0为true), document若为null返回为true
affinityIntent.getComponent().compareTo(cls) ==0&&Objects.equals(documentData,taskDocumentData)
  • 最后为affinityIntent的component。

当找到相对应的的record,且curTop不为找到record的task。这时用targetstack的moveTaskToFrontLocked. 在这些条件下addingtoTask为false &&reuseTask ==null 会做doResume操作。

  • 当 lauchflag 为clearTop或者singleInstance或者singleTask,且能在task找到历史的activityrecord。
 if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0   || launchSingleInstance || launchSingleTask) {   
 // 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.    
 ActivityRecord top =  intentActivity.task.performClearTaskLocked(r, launchFlags);  
   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(r);       
 }       
 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT,  r, top.task);     
 top.deliverNewIntentLocked(callingUid, r.intent);    
}

这里提一下FLAG_ACTIVITY_CLEAR_TOP这个方法。 当intent被标记上这个,会去task找相对应的ActivityRecord,找到后会清空其上的Activity然后做Resume(singleInstance和SignleTask也是如此)

  • 当要启动的acitivty的reactivity ( //the intent component, or target of an alias.) 跟task的realActivity相等时( task的realActivity为root)。 且 与task的root intent相等。
if(r.realActivity.equals(intentActivity.task.realActivity)
   if (!r.intent.filterEquals(intentActivity.task.intent)) {    
// In this case we are launching the root activity    
// of the task, but with a different intent.  We    
// should start a new instance on top.    
   addingToTask = true;   
   sourceRecord = intentActivity
}
  • 上面两个没匹配到, 且lauchFlags 不为reset_task
    (launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0

如果说没有做onRume操作, 后面会判断是否需要new一个新task,条件如下

if (r.resultTo == null && inTask == null && !addingToTask  && (launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) 
// In this case an activity is being launched in to an
// existing task, without resetting that task.  This
// is typically the situation of launching an activity
// from a notification or shortcut.  We want to place
// the new activity on top of the current task.

若不new task会执行

if (sourceRecord != null) {    
  final TaskRecord sourceTask = sourceRecord.task;    
  if (isLockTaskModeViolation(sourceTask)) {        
  Slog.e(TAG, "Attempted Lock Task Mode violation r=" + r);        
  return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;    
  }    
  targetStack = sourceTask.stack;    
  targetStack.moveToFront();    
  final TaskRecord topTask = targetStack.topTask();    
  if (topTask != sourceTask) {            
    targetStack.moveTaskToFrontLocked(sourceTask, r, options);    
  } else {        
    mWindowManager.moveTaskToTop(topTask.taskId);   
}

最后调用targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);


singleTop 只会判断下顶部activity是否为想调用的如果是就resumeTop

if (top != null && r.resultTo == null) {   
  if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) {            
    if (top.app != null && top.app.thread != null) {           
      if ((launchFlags & Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0 || launchSingleTop || launchSingleTask) {        
                 ...            
                 resumeTopActivitiesLocked();             
                 ...
   }   }  }  }

SingleInstance 比较特殊, 尝试去找历史Activity findActivityLocked(intent, r.info);.

/** * Returns the first activity (starting from the top of the stack) that 
* is the same as the given activity.  Returns null if no such activity 
* is found. 
*/
ActivityRecord findActivityLocked(Intent intent, ActivityInfo info) {    ComponentName cls = intent.getComponent();    
if (info.targetActivity != null) {        
cls = new ComponentName(info.packageName, info.targetActivity);    
}    
final int userId = UserHandle.getUserId(info.applicationInfo.uid);    
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {        TaskRecord task = mTaskHistory.get(taskNdx);       
   if (!isCurrentProfileLocked(task.userId)) {            
        return null;        
    }          
   final ArrayList activities = task.mActivities;        
   for (int activityNdx = activities.size() - 1; 
   activityNdx >= 0; --activityNdx) {            
   ActivityRecord r = activities.get(activityNdx);            
   if (!r.finishing && r.intent.getComponent().equals(cls) && r.userId ==   
    userId) {                
        //Slog.i(TAG, "Found matching class!");                
        //dump();                
        //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);                       
        return r;           
       }        
    }    
  }    
  return null;
}

另外当其它的activity尝试去用它所属的task时会直接将其过滤掉。

(r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE ){
if (DEBUG_TASKS) Slog.d(TAG, "Skipping " + task + ": mismatch root " + r);
continue;
}

最后说下Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET)这个flag. 如果intent被标记这个flag, 当task重置时它之上的activity都会被清掉。

if (clearWhenTaskReset) { 
// In this case, we want to finish this activity 
// and everything above it, so be sneaky and pretend
// like these are all in the reply chain.
end = numActivities - 1;
}

你可能感兴趣的:(Activity启动模式)