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

推荐阅读更多精彩内容