美文网首页
Activity启动模式

Activity启动模式

作者: o嘎嘎鱼o | 来源:发表于2015-11-16 15:45 被阅读370次

    处理启动模式的方法的是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;
    }
    

    相关文章

      网友评论

          本文标题:Activity启动模式

          本文链接:https://www.haomeiwen.com/subject/qaxkhttx.html