Android-Activity生命周期

news2024/11/23 4:12:51

文章参考:添加链接描述
文章参考:添加链接描述

五大状态

  • Starting
  • Running
  • Stopped
  • Paused
  • Destroyed
    借用一张已经包浆的图
    在这里插入图片描述
    PS:Running和Paused是可视阶段,其余都是不可视

几大函数

在这里插入图片描述

  • onCreate:通过setContentLayout初始化布局
  • onStart:此时activity可见,但没有获得焦点,无法交互,正做动画的初始化
  • onResume:获得焦点,可交互
  • onPause:如弹窗,有activity覆盖当前activity,失去焦点,但可见
  • onStop:activity不可见,系统内存紧张时会回收
  • onDestroy:结束activity

进程优先级

前台进程>可见进程>service进程>后台进程>空进程

前台进程

用户当前在做的事所必须的进程,符合其一则为

  • 进程的activity正在与用户进行交互
  • 进程持有一个service,且此service与正在交互的activity绑定/通过startForeground()在前台运行/正在进行其生命周期回调函数
  • 进程持有一个正在进行onReceive()的BroadcostReceiver

可见进程

不持有任何前台组件,但仍可见

  • 进程持有activity,此activity不在前台,处于onPause
  • 进程持有的service与可见的activtiy进行绑定

服务进程

没有和用户可见的组件绑定,所做的事情也是用户关心的,如后台下载、播放音乐的,除非内存不足,不然不会取消
当进程运行着一个startService开启的的service,且不属于前台和可见进程

后台进程

持有不可见activity,onStop调用,但没有调用onDestroy,系统会为了前三种进程任意杀死后台进程

空进程

不包含任何活跃的应用组件,则被认为是空进程
没有任何运行数据且还在内存空间,容易被杀死

启动流程

此处针对Activity A通过button点击启动位于不同进程的Activity B进行分析
在这里插入图片描述

概念梳理

  • init进程:init是所有linux程序的起点,是Zygote的父进程。解析init.rc孵化出Zygote进程。Android是基于linux系统的,手机开机之后,linux内核进行加载。加载完成之后会启动init进程。init进程会启动ServiceManager,孵化一些守护进程,并解析init.rc孵化Zygote进程
  • Zygote进程:Zygote是所有Java进程的父进程,所有的App进程都是由Zygote进程fork生成的。所有的App进程都是由Zygote进程fork生成的,包括SystemServer进程。Zygote初始化后,会注册一个等待接受消息的socket,OS层会采用socket进行IPC通信。每个应用程序都是运行在各自的Dalvik虚拟机中,应用程序每次运行都要重新初始化和启动虚拟机,这个过程会耗费很长时间。Zygote会把已经运行的虚拟机的代码和内存信息共享,起到一个预加载资源和类的作用,从而缩短启动时间。
  • SystemServer进程:System Server是Zygote孵化的第一个进程。SystemServer负责启动和管理整个Java framework,包含AMS,PMS等服务。
  • Launcher:Zygote进程孵化的第一个App进程是Launcher。
  • 进程:Android系统为每个APP分配至少一个进程
  • IPC:跨进程通信,Android中采用Binder机制。
  • ActivityStack:Activity在AMS的栈管理,用来记录已经启动的Activity的先后关系,状态信息等。通过ActivityStack决定是否需要启动新的进程。
  • ActivitySupervisor:管理 activity 任务栈
  • ActivityThread:ActivityThread 运行在UI线程(主线程),App的真正入口。
  • ApplicationThread:用来实现AMS和ActivityThread之间的交互。
  • ApplicationThreadProxy:ApplicationThread 在服务端的代理。AMS就是通过该代理ActivityThread进行通信的。
  • IActivityManager:继承与IInterface接口,抽象出跨进程通信需要实现的功能
  • AMN:运行在server端(SystemServer进程)。实现了Binder类,具体功能由子类AMS实现。
  • AMS:AMN的子类,负责管理四大组件和进程,包括生命周期和状态切换。AMS因为要和ui交互,所以极其复杂,涉及window。
  • AMP:AMS的client端代理(app进程)。了解Binder知识可以比较容易理解server端的stub和client端的proxy。AMP和AMS通过Binder通信。
  • Instrumentation:仪表盘,负责调用Activity和Application生命周期,负责监控系统与应用之间的交互。测试用到这个类比较多。
  • ActivityStackSupervisor负责所有Activity栈的管理。内部管理了mHomeStack、mFocusedStack和mLastFocusedStack三个Activity栈。
  • mHomeStack管理的是Launcher相关的Activity栈
  • mFocusedStack管理的是当前显示在前台Activity的Activity栈
  • mLastFocusedStack管理的是上一次显示在前台Activity的Activity栈

省流四步

  • A告诉AMS准备启动B
  • AMS处理请求,通知A进行Pause,A处理完后,通知AMS 自己已经完成Pause了
  • B的进程还没启动,AMS首先启动一个新的进程,新进程启动完后通知AMS服务进程启动完毕
  • AMS通知新进程启动B,B启动完毕后通知AMS服务启动完毕

AMS和应用进程间通信涉及进程间通信,与Binder有关

当创建了一个新的应用进程后,系统首先会启动ActivityThread,ActivityThread是应用进程的主线程,ActivityThread创建时会创建一个ApplicationThread对象,ApplicationThread实现了一个Binder服务端

新进程创建完时会通知AMS,同时会将ApplicationThread的代理端交付,因此AMS保存了所有应用进程的ApplicationThread的代理对象,用于给应用进程发送消息

Activity.startActivity

此处button点击函调用了该函数

public void startActivity(Intent intent, @Nullable Bundle options) {
    if (options != null) {
             //intent描述B,-1表示不返回结果
              startActivityForResult(intent, -1, options);
              ……
}

Activity. startActivityForResult

public void startActivityForResult( String who, Intent intent, int requestCode, @Nullable Bundle options) {
 Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity(
            this, mMainThread.getApplicationThread(), mToken, who,intent, requestCode, options);
   ……
}

应用程序和系统间的交互都集中交给Instrumentation来做,便于监视活动
mMainThread.getApplicationThread()是前面提到的Binder对象,实现了Binder服务端,AMS保留其client用于通信
mToken则是binder代理对象,指向AMS中保存的一个ActivityRecord信息,mToken代表了A,AMS依据其得到A的信息

Instrumentation. execStartActivity

public ActivityResult execStartActivity(Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
     ApplicationThread whoThread = (IApplicationThread) contextThread;
      try {
        //intent做进程间传输的准备工作
        intent.migrateExtraStreamToClipData();
        intent.prepareToLeaveProcess();
        //进程间传输,终于调用到AMS服务中
        int result = ActivityManagerNative.getDefault()
            .startActivity(whoThread, who.getBasePackageName(), intent,
                    intent.resolveTypeIfNeeded(who.getContentResolver()),
                    token, target != null ? target.mEmbeddedID : null,
                    requestCode, 0, null, options);
        checkStartActivityResult(result, intent);
    }
  ……
}

通过ActivityManagerNative.getDefault().startActivity()调用AMS的startActivity方法

至此都是在A的进程完成的,需要进入SystemServer中

这里调用了startActivity来启动Activity(最常用的函数),里面调用startActivityForResult,但给出的请求码是-1,即不返回数据
startActivityForResult调用了Instrumentation的execStartActivity,并传入ApplicationThread给AMS作为通信的binder对象,也传入mToken作为指向A的ActivityRecord给AMS

AMS.startActivity

public final int startActivity (IApplicationThread caller, String callingPackage,Intent intent, String resolvedType, IBinder resultTo, 
String resultWho, int requestCode,int startFlags, ProfilerInfo profilerInfo, Bundle options) {
    return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
resultWho, requestCode, startFlags, profilerInfo, options,UserHandle.getCallingUserId());
}

caller就是App1进程的ApplicationThread的binder对象,
IBinder就是指向Activity A的ActivityRecord的Binder对象,前面提到的通信和获取活动信息所需
紧接着这种方法就调用了startActivityAsUser方法

AMS. startActivityAsUser

public final int startActivityAsUser(IApplicationThread caller, String callingPackage,Intent intent,String resolvedType, IBinder resultTo, String resultWho,
 int requestCode,int startFlags, ProfilerInfo profilerInfo, Bundle options, int userId) {
        ……
        return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
        profilerInfo, null, null, options, false, userId, null, null);
}

调用了activityStackSupervisor的startActivityMayWait方法
ActivityStackSupervisor是Activity调度的核心类
Activity的调度相关的工作都是在ActivityStackSuperVisor中处理
主要管理Task和Stack.它是在AMS启动的时候创建的。

startActivityMayWait

final int startActivityMayWait(IApplicationThread caller, int callingUid,String callingPackage, Intent intent, String resolvedType,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,IBinder resultTo, String resultWho, int requestCode, int startFlags,
ProfilerInfo profilerInfo, WaitResult outResult, Configuration config,Bundle options, boolean ignoreTargetSecurity, int userId,
IActivityContainer iContainer, TaskRecord inTask) {
   ……
  //PMS服务依据intent查询要启动的Activity B的信息,保存到ActivityInfo中
  intent = new Intent(intent);
  ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags, profilerInfo, userId);
  //决定当前活动的stack
  ActivityContainer container = (ActivityContainer)iContainer;
  final ActivityStack stack;
  if (container == null || container.mStack.isOnHomeDisplay()) {
    stack = mFocusedStack;
  } else {
    stack = container.mStack;
  }
   ……
   //将PMS中查询到的Activity B的信息当做參数
   int res = startActivityLocked(caller, intent, resolvedType, aInfo,voiceSession, voiceInteractor, resultTo, resultWho,requestCode, callingPid, callingUid, callingPackage,
                realCallingPid, realCallingUid, startFlags, options, ignoreTargetSecurity,componentSpecified, null, container, inTask);
      ……
}

resolveActivity调用PMS服务依据Intent信息查询B的具体信息
查询是否有对应的ActivityStack,若传递过来的container为空,则指定Stack为当前获得焦点的ActivityStack,即mFocusedStack

ActivityStack分为几种

  • Home Stack 为 Launcher所在的Stack,一些系统界面也在此Stack执行,SystemUI等
  • FullScreen Stack 全屏的Activity所在的Stack,最常用
  • Freeform模式的Activity所在Stack,即可以自由缩放,自由移动
  • Docked Stack,分屏模式
  • Pinned Stack 画中画

startActivityLocked

final int startActivityLocked(IApplicationThread caller,Intent intent, String resolvedType, ActivityInfo aInfo,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,IBinder resultTo, String resultWho, int requestCode,int callingPid, int callingUid, String callingPackage,int realCallingPid, int realCallingUid, int startFlags, Bundle options,
boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity,ActivityContainer container, TaskRecord inTask) {
       //callerApp 代表调用方的应用进程。即App1的应用进程
    ProcessRecord callerApp = null;
    if (caller != null) {
	    //依据caller找到AMS中保存的App1的processRecord对象
        callerApp = mService.getRecordForAppLocked(caller);
        if (callerApp != null) {
		    //得到App1应用进程的pid和应用的uid
            callingPid = callerApp.pid;
            callingUid = callerApp.info.uid;
        }
		……
    }
    ……
	//即调用者的Activity组件
    ActivityRecord sourceRecord = null;
	//返回结果的Activity组件
    ActivityRecord resultRecord = null;
    if (resultTo != null) {
	    //依据resultTo Binder对象得到其指向的ActivityRecord,即Activity A的ActivityRecord信息
        sourceRecord = isInAnyStackLocked(resultTo);
        //普通情况下请求的Activity和要接收返回结果的Activity是同一个
        if (sourceRecord != null) {
            if (requestCode >= 0 && !sourceRecord.finishing) {
                resultRecord = sourceRecord;
            }
        }
    }
    final int launchFlags = intent.getFlags();
    ……
    //依据准备的信息,创建一个即将启动的ActivityRecord对象。即Activity B
    ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
            intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,
            requestCode, componentSpecified, voiceSession != null, this, container, options);
    ……
    //将刚创建的目标Activity的ActivityRecord作为參数,继续调用startActivityUncheckedLocked方法来启动
    err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor,
            startFlags, true, options, inTask);
    ……
    return err;
}

依据传入的A的binder对象caller获得A的ActivityRecord信息,获取调用程序的pid和uid
加上ainfo创建一个ActivityRecord对象r,代表B
至此sourceRecord获取了A的组件消息,r获取了B的信息
最终调用startActivityUncheckedLocked启动B

startActivityUncheckedLocked

final int startActivityUncheckedLocked(final ActivityRecord r, ActivityRecord sourceRecord,IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags,
boolean doResume, Bundle options, TaskRecord inTask) {
    //依据flag获取对应的启动模式。我们代码中没有设置启动模式,所以默认应该是标准模式。这三个变量都应该是false		
    final boolean launchSingleTop = r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP;
    final boolean launchSingleInstance = r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE;
    final boolean launchSingleTask = r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK;
	……
	//即将要启动activity的 task
	ActivityStack targetStack;
	……
	//是否新建一个Task
	boolean newTask = false;
	……
	//获取Activity A的Task,然后赋值给B,即两个Activity位于同一个Task中
	 else if (sourceRecord != null) {
       //获取Activity A所在的Task
       final TaskRecord sourceTask = sourceRecord.task;
       //将A所在的ActivityStack作为B启动的Stack
       targetStack = sourceTask.stack;
       targetStack.moveToFront("sourceStackToFront");
       //获取ActivityStack中的 top Task是不是和当前的Task一致,假设不一致则将当前的Task移动到ActivityStack的顶端
       final TaskRecord topTask = targetStack.topTask();
       if (topTask != sourceTask) {
         targetStack.moveTaskToFrontLocked(sourceTask, noAnimation, options,r.appTimeTracker, "sourceTaskToFront");
       }
      ……
      //将当前Activity Stack mLastPausedActivity设置为null
      targetStack.mLastPausedActivity = null;
      //调用startActivityLocked方法
      targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
}

这里处理了Activity四种启动模式,根据Intent中的flag标志来决定不同的启动模式和Activity在Task中的位置
此处的启动模式是默认的,因此A和B同放在一个Task里面

每个Activity都位于一个Task中,一个Task能够包括多个Activity,同一个Activity也可由多个实例

Task管理在于近期任务列表和Back栈,AMS和WMS内部有一个容器Stack,android多窗体管理建立在Stack上,一个Stack中多个Task,一个Task包括多个Activity

最后调用ActivityTask的startActivityLocked启动

ActivityStack . startActivityLocked

final void startActivityLocked(ActivityRecord r, boolean newTask,boolean doResume, boolean keepCurTransition, Bundle options) {
    //获取要启动的Task对象
   TaskRecord rTask = r.task;
   final int taskId = rTask.taskId;
   TaskRecord task = null;
   if (!newTask) {
        //遍历AMS中全部的Task,找到目标task,然后将即将要启动的Activity增加到Task的栈顶
        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) {
                
                if (!startIt) {
                    task.addActivityToTop(r);
                    r.putInHistory();
                    ……
	//传入的resume位true。然后调用resumeTopActivitiesLocked方法继续启动Activity			
    if (doResume) {
        mStackSupervisor.resumeTopActivitiesLocked(this, r, options);
    }

遍历全部Task,找到目标Task,将即将要启动的Activity的ActivityRecord增加到栈顶

ActivityStackSuperVisor. resumeTopActivitiesLocked

boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target, Bundle targetOptions) {
       //假设目标task是frontStack调用resumeTopActivityLocked
    if (isFrontStack(targetStack)) {
        result = targetStack.resumeTopActivityLocked(target, targetOptions);
    }
    //然后遍历找到时frontStack的task运行resumeTopActivityLocked
    for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
        ……
            }
            if (isFrontStack(stack)) {
                stack.resumeTopActivityLocked(null);
            }
     ……

确认目标task是否为frontStack,若是则直接执行resumeTopActivityLocked,不是则遍历,找到对应的frontStack执行resumeTopActivityLocked

ActivityStack.resumeTopActivityLocked

直接有调用了resumeTopActivityInnerLocked方法

ActivityStack. resumeTopActivityInnerLocked

ActivityStack. resumeTopActivityInnerLocked private boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) {
   ……
  //找到栈顶第一个不是处于finishing状态的ActicityRecord
  final ActivityRecord next = topRunningActivityLocked(null);
  ……
  //调用startPausingLocked方法来暂停上一个Activity
  if (mResumedActivity != null) {
    if (DEBUG_STATES) 
        Slog.d(TAG_STATES,"resumeTopActivityLocked: Pausing " + mResumedActivity);
    pausing |= startPausingLocked(userLeaving, false, true, dontWaitForPause);
}

topRunningActivityLocked找到当前栈顶不是处于fininshiing状态的第一个ActivityRecord
将B的ActivityRecord添加到当前Task的栈顶,即next
startPausingLocked暂停上一个Activity
ActivityStack有三个成员变量:mResumedActivity、mLastResumedActivity、mLastPausedActivity

  • mResumedActivity:栈中激活状态的activity
  • mLastResumedActivity:栈中上一次被暂停的activity
  • mLastPausedActivity:栈中正在被暂停的activity
    mResumedActivity != null表示A不为空,暂停A

总结 startActivity到Pause

Activity的startActivity方法启动目标Activity

Instrumentation的方法execStartActivity,方便Instrumentation对交互进行监測

以上部分是在App1的进程中运行。之后会通过进程间通信调用到AMS服务中调用AMS的startActivity方法。

此时进入SystemServer进程。

然后由AMS中管理Acticity核心调度的类ActivityStackSupervisor的方法startActivityMayWait来处理。该方法中主要是依据Intent从PMS中查询目标Activity的信息

ActivityStackSuperVisor的startActivityLocked方法主要是在AMS中找调用进程的processRecord信息,调用Activity的ActivityRecord信息。目标Activity还没有启动,所以须要先创建一个目标Activity的ActivityRecord信息。

ActivityStackSuperVisor的StartActivityUncheckedLocked方法主要来处理启动模式相关的逻辑,依据不同的启动模式,找到对应的对的ActivityStack,然后又对应的ActivityStack进行处理

ActivityStack将目标Activity增加到相应的Task栈顶

调用ActivityStackSuperVisor的resumeTopActivityLocked方法找到处于前台的Task。然后调用它的resumeTopActivityLocked方法激活目标Activity.

当前的Task的栈開始Pasuing调用的Activity

以上几个步骤完成AMS对调用Activity及目标Activity的信息收集处理
拿到启动进程的binder对象和A的activityRecord给AMS
通过ActivityStackSuperVisor拿到启动进程的信息
根据Intent拿到目标Activity的信息
依据启动模式来决定将目标Activity方法那个栈中。然后将目标栈当前处于激活状态的Activity Pause掉给目标Activity腾地方。

Activity Resume - Pause

ActivityStack.startPausingLocked

final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping, boolean resuming,boolean dontWait) {
   //mResumeActivity代表当前激活的Activity。即Activity A
   ActivityRecord prev = mResumedActivity;
   ……
   //当前处于激活状态mResumedActivity 的设置为null
   mResumedActivity = null;
   //即将要处于pasuing状态的Activity 就是Activity A
   mPausingActivity = prev;
   mLastPausedActivity = prev;
   ……
   //将Activity A的状态设置为PAUSING
   prev.state = ActivityState.PAUSING;
   //找到当前的栈顶的topActivity就是 Activity B
   final ActivityRecord next = mStackSupervisor.topRunningActivityLocked();
   //调用进程不为null,且调用进程的ApplicationThread不为null
   if (prev.app != null && prev.app.thread != null) {
     try {
           ……
          //通过调用进程的ApplicationThread通知调用进程schedulePauseActivity方法
          prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,userLeaving, prev.configChangeFlags, dontWait);
          }

从mResumeActivity拿到A的ActivityRecord,赋值prev
并将其和B设为pause状态,因为B暂时未启动,未激活
prev.app代表A的ProcessRecord,prev.app.thread则为A所在进程的ApplicationThread
通过ApplicationThread可以得到进程的Binder client,使得AMS能够向应用进程发送消息
最终通过调用A的schedulePauseActivity,完成Pause

ApplicationThread. schedulePauseActivity

public final void schedulePauseActivity(IBinder token, boolean finished,boolean userLeaving, int configChanges, boolean dontReport) {
    sendMessage(finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,token,(userLeaving ?1 : 0) | (dontReport ? 2 : 0),configChanges);
}

应用进程的ApplicationThread是ActivityThread的一个内部类,token是一个Binder类型的对象,指向了AMS中与A的ActivityRecord,根据finish决定是暂停结束还是暂停
这里发送了PAUSE_ACTIVITY的message给handler

……
handlePauseActivity((IBinder)msg.obj, false, (msg.arg1&1) != 0, msg.arg2,(msg.arg1&2) != 0);

ActivityThread.handPauseActivity

private void handlePauseActivity(IBinder token, boolean finished,
boolean userLeaving, int configChanges, boolean dontReport) {
ActivityClientRecord r = mActivities.get(token);
if (r != null) {
     //调用Activity A的onPause方法
     performPauseActivity(token, finished, r.isPreHoneycomb());
        //等待pause状态的数据写入完毕.
        if (r.isPreHoneycomb()) {
            QueuedWork.waitToFinish();
        }
         ……
        try {
            //进程间通信。调用AMS的ActivityPause方法
            ActivityManagerNative.getDefault().activityPaused(token);
            } catch (RemoteException ex) {}

ActivityThread中的mActivites集合中保存了当前进程的所有Activity,每个Activity都用一个ActivityClientRecord表示,集合中以binder为key保存
AMS中的全部Activity也是在一个集合中存储,以ActivityRecord来表示,key值也是Binder对象

此处由token获取获取ActivityClientRecord
performPauseActivity调用了A的onSaveInstance,然后调用了onPause
因为onSaveInstance需要存储当前Activity的信息,进行I/O操作,所以需要QueuedWork.waitToFinish来等待存储完成
最后调用activityPaused,进入SystemServer进程

AMS.activityPaused

public final void activityPaused(IBinder token) {
   //获取Activity 所在的ActivityStack
   ActivityStack stack = ActivityRecord.getStackLocked(token);
  if (stack != null) {
    //调用目标ActivityStack的activityPauseLocked方法
     stack.activityPausedLocked(token, false);
    }
 }

Token代表的是Activity A ,此处依据token找到Activity A所在的ActivityStack,然后由目标Stack来处理activityPause逻辑

ActivityStack.activityPauseLocked

final void activityPausedLocked(IBinder token, boolean timeout) {
    //依据token获取Activity A的ActivityRecord对象
    final ActivityRecord r = isInStackLocked(token);
    if (r != null) {
    //移除pause超时消息
    mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
    if (mPausingActivity == r) {
    //调用completePauseLocked方法继续运行pause逻辑
    completePauseLocked(true);
}
……

当运行完pause逻辑的ActivityRecord和我们运行pause逻辑前的activityRecord一样的时候,即是同一个Activity。
就能够调用completePauseLocked方法来完毕Activity A Pause最后的逻辑了。

ActivityStack. completePauseLocked

if (resumeNext) {
  final ActivityStack topStack = mStackSupervisor.getFocusedStack();
  if (!mService.isSleepingOrShuttingDown()) {
     mStackSupervisor.resumeTopActivitiesLocked(topStack, prev, null);
  }
  ……
}

resumeNext就是completePauseLocked传进来的參数,为true。
调用mStackSupervisor的getFocusedStack()方法来获取正在处理的ActivityStack. mService.isSleepingOrShuttingDown。推断AMS服务是否处于正常激活状态
然后调用mStackSupervisor的resumeTopActivitiesLocked继续处理。

ActivityStackSuperVisor.resumeTopActivitiesLocked

假设当前的ActivityStack是frontStack。
直接调用ActivityStack的resumeTopActivityLocked。
ActivityStack的resumeTopActivityLocked方法则直接有调用了ActivityStack的resumeTopActivityInnerLocked方法。

ActivityStack. resumeTopActivityInnerLocked

private boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) {
 ……
    //找到栈顶的Activity,此时栈顶的acitvity就是即将要启动的Activity B
    final ActivityRecord next = topRunningActivityLocked(null);
         ……
    //我们知道,在前面Activity A变为pause状态的时候。我们就把mResumeActivity 置为了Null
	if (mResumedActivity != null) {
        if (DEBUG_STATES) Slog.d(TAG_STATES,
                "resumeTopActivityLocked: Pausing " + mResumedActivity);
        pausing |= startPausingLocked(userLeaving, false, true, dontWaitForPause);
    }
	……
	//即将要启动的Activity处于一个新的进程,眼下还没有启动
	if (next.app != null && next.app.thread != null) {
		……
	}else{
		……
		//来启动目标Activity
		mStackSupervisor.startSpecificActivityLocked(next, true, true);
	}

推断mResumeActivity不为空,说明当前有一个处于正在激活状态的Activity,须要先将原先的Activity变为pause状态。
当Activity A变为Pause状态后。再次走到这种方法来激活目标Activity,此时mResumeActivity已经为空,所以不须要再运行pause的逻辑。
然后推断目标Activity next的进程app和ApplicationThread是否为空,由于Activity A 所在的进程还没有创建,所以两个都为空,直接运行mStackSupervisor的startSpecificActivityLocked来启动新的Activity。

此阶段由ActivityStack.startPausingLocked开始,将A进行Pause,调用onRestoreinstance保存信息等,修改当前的ActivityStack的激活activity等信息,然后定位B的ActivityStack,暂停栈顶Activity,并启动新进程

启动新进程

ActivityStackSuperVisor. startSpecificActivityLocked

void startSpecificActivityLocked(ActivityRecord r,boolean andResume, boolean checkConfig) {
   //获取目标Activity的进程ProcessRecord
   ProcessRecord app = mService.getProcessRecordLocked(r.processName,r.info.applicationInfo.uid, true);
   ……
  //因为目标Activity所在进程还没有创建,所以为空
  if (app != null && app.thread != null) {
    ……
   }
    //
   mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,"activity", r.intent.getComponent(), false, false, true);
}

该方法比較简单,依据目标Activity的ProcessName来查找相应的ProcessRecord.
依据processRecord中的进程app和ApplicationThread来推断
假设这两个变量不为空,说明目标Activity的进程和执行环境已经具备
直接启动Activity就能够,我们知道眼下目标Activity的进程还没有启动,所以须要调用AMS先启动一个目标Activity的进程

AMS. startProcessLocked

final ProcessRecord startProcessLocked(String processName, ApplicationInfo info,……) {
    long startTime = SystemClock.elapsedRealtime();
    ProcessRecord app;
    if (!isolated) {
        app = getProcessRecordLocked(processName, info.uid, keepIfLarge);
        String hostingNameStr = hostingName != null?hostingName.flattenToShortString()null
        ……
	    startProcessLocked(app, hostingType, hostingNameStr, abiOverride, entryPoint, entryPointArgs);
	    ……
	}
	……
}

获得ProcessRecord,调用startProcessLocked

private final void startProcessLocked(ProcessRecord app, String hostingType,String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
		int uid = app.uid;
        int[] gids = null;
		……
		//從PMS服务中查找目标应用相应的权限组
		final IPackageManager pm = AppGlobals.getPackageManager();
        permGids = pm.getPackageGids(app.info.packageName, app.userId);
		……
		gids = new int[permGids.length + 2];
        System.arraycopy(permGids, 0, gids, 2, permGids.length);
		……
		app.gids = gids;
		……
		if (entryPoint == null) entryPoint = "android.app.ActivityThread";
		 //调用Process的静态方法启动一个新的进程 
	   Process.ProcessStartResult startResult = Process.start(entryPoint,
                app.processName, uid, uid, gids, debugFlags, mountExternal,
                app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
                app.info.dataDir, entryPointArgs);

这种方法做的主要工作就是调用Process的静态方法启动一个新的进程。
启动新的进程的过程大概是
Zygote进程会fork一个新的子进程出来,子进程创建完毕之后
classLoader载入ActivityThread类并创建一个ActivityThread实例
反射调用ActivityThread的main方法
这样ActivityThread主线程就在新的进程中启动起来了。
接着看ActivityThread的main方法,此时已经在新的进程中运行了。

ActivityThread.main

public static void main(String[] args) {
    Looper.prepareMainLooper();
    ActivityThread thread = new ActivityThread();
    thread.attach(false);
    if (sMainThreadHandler == null) {
        sMainThreadHandler = thread.getHandler();
    } 
    Looper.loop();

这种方法主要工作就是调用Looper.prepareMainLooper创建一个消息循环队列
然后调用Looper.loop进入消息循环,当前线程进入消息循环中
使当前线程成为新进程的主线程,然后创建一个ActivityThread对象。调用Attach方法。

ActivityThread.attach

final ApplicationThread mAppThread = new ApplicationThread();
private void attach(boolean system) {
    sCurrentActivityThread = this;
    mSystemThread = system;
    if (!system) {
      ……
      final IActivityManager mgr = ActivityManagerNative.getDefault();
      try {
        mgr.attachApplication(mAppThread);
     } catch (RemoteException ex) {
       // Ignore
     }
     ……
   } else {
  }

初始系统进程的执行环境的时传入的參数system为true,表示是系统进程
而这次是普通的应用进程,所以參数system为false
ActivityManagerNative.getDefault()方法获取AMS的代理
调用attachApplication方法发送一个进程间通信的请求,将创建的ApplicationThread对象传递给AMS服务
ApplicationThread是一个ActivityThread本地binder对象,Binder的服务端在ActivityThread中,将Binder对象传递给AMS服务。则AMS服务中保存它的代理,AMS就获得了与新进程通信的方式。
此前的代码运行在新建的进程中。即应用App2所在的进程,然后通过进程间通信

AMS.attachApplication

      ApplicationInfo appInfo = app.instrumentationInfo != null? app.instrumentationInfo : app.info;		
        //进程间调用:调用新进程的bindApplication方法
        thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,
                profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,
                app.instrumentationUiAutomationConnection, testMode, enableOpenGlTrace,
                isRestrictedBackupMode || !normalMode, app.persistent,
                new Configuration(mConfiguration), app.compat,
                getCommonServicesLocked(app.isolated),
                mCoreSettingsObserver.getCoreSettingsLocked());
         ……
        if (normalMode) {
           try {
		       //调用ActivityStackSupervisor的方法来启动新的Activity
               if (mStackSupervisor.attachApplicationLocked(app)) {
                   didSomething = true;
               }
           }
	     ……
   }

依据进程ID,查询相应进程的ProcessRecord,这个ProcessRecord是新进程的对象,指向新进程
从PMS中查询与新进程相关的ContentProvider的信息
这里的thread是新进程的ApplicationThread的binder,调用新进程的handlebindApplication来初始化执行环境,包含新进程Application的初始化、Instrumentation的初始化和安装相关的ContentProvider
最后调用ActivityStackSupervisor执行attachApplication

ActivityStackSuperVisor. attachApplicationLocked

boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {
  final String processName = app.processName;
  //遍历全部的stack,找到处于前台的ActivityStack
  for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
    ArrayList stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
    for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
    final ActivityStack stack = stacks.get(stackNdx);
    if (!isFrontStack(stack)) {
         continue;
    }
  //找到处于栈顶的ActivityRecord
   ActivityRecord hr = stack.topRunningActivityLocked(null);
  if (hr != null) {
     if (hr.app == null && app.uid == hr.info.applicationInfo.uid&& processName.equals(hr.processName)) {
       try {
          //调用realstartActivityLocked方法来启动目标Activity
          if (realStartActivityLocked(hr, app, true, true)) {
             didSomething = true;
          }
       } catch (RemoteException e) {
             ……
     }
}

遍历并找到目标stack,然后拿到这个ActivityStack栈顶的ActivityRecord,这就是目标Activity
之前放到栈顶的。得到要启动的Activity信息之后启动新的Activity

ActivityStackSuperVisor. realStartActivityLocked

final boolean realStartActivityLocked(ActivityRecord r,ProcessRecord app, boolean andResume, boolean checkConfig)throws RemoteException {
         ……
        //将新进程的信息保存到ActivityRecord的app变量中
        r.app = app;
		//获取目标Task
		final TaskRecord task = r.task;
		//找到Task对用的Stack
		final ActivityStack stack = task.stack;
		//跨进程调用,通知目标进程来启动Activity
		app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
                new Configuration(stack.mOverrideConfig), r.compat, r.launchedFromPackage,
                task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,
                newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);
}

将ActivityRecord的app对象指向了新的进程。这样ActivityRecord就和新的进程关联了起来。
然后通过目标进程ApplicationThread代理Binder对象发起进程间通信请求,调用目标进程的scheduleLaunchActivity方法来启动新的Activity

ApplicationThread. scheduleLaunchActivity

 public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,ActivityInfo info, Configuration curConfig,…… ProfilerInfo profilerInfo) {
        updateProcessState(procState, false);
		//依据进程间传递的消息,初始化ActivityClientRecord
        ActivityClientRecord r = new ActivityClientRecord();
        r.token = token;
        r.ident = ident;
		……
		//发送消息,终于有Handler来处理
        sendMessage(H.LAUNCH_ACTIVITY, r);
    }

调用到ActivityThread内部的ApplicationThread中
该ApplicationThread实现了ApplicationThreadNative,这样就实现了进程间通信的Binder服务端
发送消息,由Handler的HandMessage来处理
在handleMessage中又调用了ActivityThread的handleLaunchActivity来处理

ActivityThread.handleLaunchActivity

private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
  //调用performLaunchActivity方法来启动Activity
  Activity a = performLaunchActivity(r, customIntent);
  //Activity启动完毕后。调用handlResumeActivity来使Activity进入resume激活状态
  if (a != null) {
        r.createdConfig = new Configuration(mConfiguration);
        Bundle oldState = r.state;
        handleResumeActivity(r.token, false, r.isForward,!r.activity.mFinished && !r.startsNotResumed);
        }
}

首先调用performLaunchActivity来创建一个Activity对象,并调用Activity的onCreate方法完毕Activity启动
随后调用handleResumeActivity方法。激活Activity,时Activity计入resume状态

ActivityThread.performLaunchActivity

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    ActivityInfo aInfo = r.activityInfo;
    //获取Activity的packageInfo信息
   if (r.packageInfo == null) {
      r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,Context.CONTEXT_INCLUDE_CODE);
}
   //获取Activity的Component信息
   ComponentName component = r.intent.getComponent();
   if (component == null) {
     component = r.intent.resolveActivity(mInitialApplication.getPackageManager());r.intent.setComponent(component);
}
   if (r.activityInfo.targetActivity != null) {
     component = new ComponentName(r.activityInfo.packageName,r.activityInfo.targetActivity);
}
    //调用Instrumentation类来创建一个依据Activity的信息Activity对象
    Activity activity = null;
    java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
    activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
    //创建完毕后,调用Activity的attach方法来初始化Activity
    if (activity != null) {
            Context appContext = createBaseContextForActivity(r, activity);
            CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
            Configuration config = new Configuration(mCompatConfiguration);
            if (DEBUG_CONFIGURATION) 
                 Slog.v(TAG, "Launching activity "+ r.activityInfo.name + " with config " + config);
            activity.attach(appContext, this, getInstrumentation(), r.token,
                    r.ident, app, r.intent, r.activityInfo, title, r.parent,
                    r.embeddedID, r.lastNonConfigurationInstances, config,
                    r.referrer, r.voiceInteractor);

     ……
    //调用Activity的onCreate方法
   mInstrumentation.callActivityOnCreate(activity, r.state);
   ……
   //运行Activity的onStart方法
   if (!r.activity.mFinished) {
                activity.performStart();
                r.stopped = false;
            }
   ……
   //调用Activity的onRestoreInstancestate方法
   if (r.state != null) {
              mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
   ……
  //调用Activity的onPostCreate方法
  mInstrumentation.callActivityOnPostCreate(activity, r.state);
   ……
  //把创建的相应的ActivityClientRecord以binder为键值,保存到mActivities中
  mActivities.put(r.token, r);

在新的进程中,依据AMS传递过来的信息创建了一个ActivityClientRecord对象。该对象和AMS服务中的一个ActivityRecord相应。

在这种方法中。依据目标Activity B的ActivityClientRecord,调用Instrumentation类来创建一个Acitivity,创建过程就是ClassLoader载入相应的Activity类,用反射方法创建一个对象。

创建完新的Activity对象后,即Activity B的对象,然后调用它的onCreate方法,这样Activity B的onCreate对象就会被调用,以便载入自定义的用户界面,以及其它的初始化方法。

onCreate方法调用完毕之后。
然后依次调用ActivityonStart,onRestoreInstanceState,onPostCreate方法等,这个就是Activity生命周期运行的逻辑。

创建新进程的总结:
通过Zygote创建新进程,在其main方法中创建消息队列和application。
创建Application传给AMS,查找目标Activity所在的stack,拿到位于栈顶的ActivtiyRecord,对新进程和ActivityRecord进行关联,通过发送消息调用ActivityThread调用handleLaunchActivity来调用performLaunchActivity完成activity的onCreate和activity的onResume

到此为止。ActivityB就启动完毕了,它启动起来之后,意味着ActivityB所在的应用程序也就启动起来了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/610556.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何选择最佳数据库:MongoDB、PostgreSQL或ScyllaDB?

Tractian是一家提供工业监控系统的机器智能公司。去年,我们面临着将我们的实时机器学习(ML)环境和分析仪表板升级以支持数据吞吐量的大幅增长的挑战,因为我们成功地将客户数据库和数据量扩大了10倍。 我们意识到,在快…

MySQL版本5.7.99?

序:在项目工作中需要从三方厂商数据库同步数据到项目业务库中,本平平无奇的功能却被一个报错打破。 在使用某框架的DataSourceConfig(Object)方法初始化数据库连接时,日志输出报错: Unknown system variable transaction_isolatio…

sparkRDD编程实战

文章目录 sparkRDD编程实战1、Spark RDD 实现单词计数2、Spark RDD 实现分组求TopN3、Spark RDD 实现二次排序4、Spark RDD 计算平均成绩5、Spark RDD 倒排索引统计每日新增用户6、Spark案例实操7、Spark RDD 综合应用需求1:Top10热门品类需求说明实现方案一实现方案…

【Python SMTP/POP3/IMAP】零基础也能轻松掌握的学习路线与参考资料

Python是一种高级编程语言,广泛应用于Web开发、人工智能、数据科学、自动化等领域。SMTP/POP3/IMAP是与邮件相关的三个协议,分别用于发送邮件、接收邮件和访问邮件。使用Python可以轻松实现这些功能,本文将介绍Python SMTP/POP3/IMAP的学习路…

【Python】Python系列教程-- Python3 条件控制(十六)

文章目录 前言if 语句if 嵌套match...case 前言 往期回顾: Python系列教程–Python3介绍(一)Python系列教程–Python3 环境搭建(二)Python系列教程–Python3 VScode(三)Python系列教程–Pytho…

Spring Boot整合Swagger2 Swagger2配置

目录 什么是Swagger? Swagger如何使用 如何使用Swagger 查看SwaggerAPI文档 什么是Swagger? Swagger是一款流行的RESTful API文档生成工具,它支持多种编程语言和多种框架,包括但不限于Java、Python、Node.js、Go等,Spring Boot也提供了…

【机器学习】第二章:K近邻(分类)

系列文章目录 第二章:K近邻(分类) 相关代码地址:https://github.com/wzybmw888/MachineLearning.git 文章目录 系列文章目录一、最近邻算法二、最近邻算法的缺陷(1)策略一:K近邻(k‐…

java源码为什么需要编译成字节码?

作用1: jvm支持多语言,需要字节码作为统一的规范 作用2: 字节码转成机器的指令会更快 作用3: 如果没有对应的反编译器,字节码还具有一定的安全保密作用

【Rust日报】2023-06-02 Rust 1.70.0 稳定版发布

Rust 1.70.0 稳定版发布 Rust 团队很高兴地宣布 Rust 的新版本 1.70.0。Rust 是一种编程语言,它使每个人都能构建可靠、高效的软件。 最大的特性是,OnceCell稳定版可用啦。 如果你通过 rustup 安装了以前版本的 Rust,你可以通过以下方式获得 …

Linux 之大数据定制篇-Shell 编程

Linux 之大数据定制篇-Shell 编程 为什么要学习Shell 编程 Linux 运维工程师在进行服务器集群管理时,需要编写Shell 程序来进行服务器管理。对于JavaEE 和Python 程序员来说,工作的需要,你的老大会要求你编写一些Shell 脚本进行程序或者是服…

Mocha AE:图层相关面板

Mocha AE 左侧的图层面板、图层属性面板以及边缘属性面板提供了与图层、样条、跟踪等相关的选项。 Layers 图层 图层的上下顺序相当重要。 上方所有图层的样条区域将被自动排除出跟踪遮罩 Track Mattes。 也可在同一图层上绘制多个样条形状。相交的样条区域将被排除出遮罩。 Vi…

【MySQL】一文带你了解MySQL中的子查询

文章目录 1. 需求分析与问题解决1. 1实际问题1.2 子查询的基本使用1.3 子查询的分类 2. 单行子查询2.1 单行比较操作符2.2 代码示例2.3 HAVING 中的子查询2.4 注意的问题 3. 多行子查询3.1 多行比较操作符3.2 代码示例 4. 相关子查询4.1 相关子查询执行流程4.2 代码示例 子查询…

图论学习(六)

图的连通度 删去任意一条边后便不连通 删去任意一条边后仍连通,但删去点u后不连通。 G3和G4删去任意一条边或任意一个点后仍连通,但从直观上看,G4的连通程度比G3高。 割边 设e是图G的一条边,若ω(G-e)>ω(G),则…

uniapp微信一键登录微信授权

前言 现在小程序逐渐成为主流,常用的微信授权登录很重要很常见的一个功能,今天自己总结了一下。 准备工作 1.如果你想自己想试一下这个功能首先你需要有一个开发中的项目并且你在开发成员里面。 2.配置自己的微信开发者工具的appid码 3.在hbuilderx的…

echarts 如何实现图例单个数据项加上背景颜色和饼图中的背景图自适应

需求: 实现效果如下: ECharts中,可以通过设置legend中的formatter属性来自定义图例项的显示格式。以下是一个示例: option = {// ...legend: {data: [A, B, C],formatter: function (name) {var color = #fff;if (name === A) {color = #ff0000; // 设置A的背景颜色为红色…

如何使用ArcGIS计算容积率

字段计算 为建筑图层新建一个area字段,用于记录单层建筑的面积,如下图所示。 单层建筑面积 为建筑图层新建一个areaAll字段,用于记录总建筑面积,areaAllarea*floor,如下图所示。 计算总面积 为小区图层新建一个area…

chatgpt赋能python:Python大于0的SEO

Python大于0的SEO Python是一种高级编程语言,被广泛用于数据科学、机器学习、Web应用程序和网络爬虫等领域。Python大于0的SEO是指使用Python编写程序来优化网站的排名。在本文中,我们将介绍Python大于0的SEO的基础知识和一些实用技巧。 什么是Python大…

【redis基础】哨兵

hi,这里是redis系列文章,本篇是【redis基础】哨兵,上一篇链接:【redis】redis主从复制_努力努力再努力mlx的博客-CSDN博客 目录 概念 作用 如何使用哨兵(案例演示实战步骤) redis sentinel架构提前说明 重点参数…

【Java】Java(四十九):注解及自定义注解

文章目录 什么是注解?概述注解的作用自定义注解注解的定义格式带有属性的注解 注解的使用注解的使用格式 元注解元注解的作用:常用元注解: 注解解析 什么是注解? 注解(Annotation)也称为元数据,是一种代码级别的说明注…

数据库管理-第八十期 Exadata to RAC(x86) ADG(20230605)

数据库管理 2023-06-05 第八十期 Exadata to RAC(x86) ADG1 环境2 搭建流程2.1配置静态监听-主库2.2配置静态监听-备库2.3配置本地命名-主备库2.4数据库配置-主库2.5生成参数文件和密码文件-主库2.6创建目录并上传密码文件-备库2.7添加数据库服务-备库2.8修改参数文件-备库2.9复…