文档章节

深入理解Android-Activity的启动过程

天王盖地虎626
 天王盖地虎626
发布于 06/20 19:00
字数 4172
阅读 12
收藏 1

一、准备工作

1、准备好阅读源码的工具。

2、主要类的功能介绍

  • ActivityManagerServices 简称AMS,服务端对象,是Android中最核心的服务,主要负责系统中四大组件的启动、切换和调度及应用进程的管理和调度工作。负责系统中所有Activity的生命周期.(深入理解Android 卷II 对此有进行深入的讲解 http://wiki.jikexueyuan.com/project/deep-android-v2/activity.html)。
  • ActivityThread ,APP的真正入口。当开启APP后,会调用main()开始运行,开启消息循环队列,这就是传说中的UI或者叫主线程,与AMS配合使用,一起完成Activity 的管理工作。
  • Instrumentation ,每一个应用程序只有一个Instrumentation对象,每个activity内都有一个对该对象的引用。Instrumentation可以理解为应用进程的管家,ActivityThread要创建和暂停某个activity时,都需要通过Instrumentation来进行具体的操作。
  • ApplicationThread 用来实现AMS 与 ActivityThread 之间的交互。在AMS需要管理相关Application中的Activity的生命周期时,通过ApplicationThread的代理对象与ActivityThread通讯。
  • ApplicationThreadProxy,是ApplicationThread在服务端的代理,负责和客户端的ApplicationThread通讯。AMS就是通过该代理与ActivityThread通讯的。
  • ActivityStack,Activity在AMS的栈管理,用来记录已经启动的Activity的先后关系,状态信息等。通过ActivityStack决定是否需要启动新的进程。
  • ActivityRecord,ActivityStack的管理对象,每个Activity在AMS对应一个ActivityRecord,来记录Activity的状态以及其他的管理信息。其实就是服务器端的Activity对象的映像。
  • TaskRecord,AMS抽象出来的一个“任务”的概念,是记录ActivityRecord的栈,一个“Task”包含若干个ActivityRecord。AMS用TaskRecord确保Activity启动和退出的顺序。如果你清楚Activity的4种launchMode,那么对这个概念应该不陌生。

二、启动过程分析

我们从源码的package android.app.Activity.java 的 startActivity 方法分析,其中 startActivity 方法有几种重载方式:

@Override
    public void startActivity(Intent intent) {
        this.startActivity(intent, null);
    }
   @Override
    public void startActivity(Intent intent, @Nullable Bundle options) {
        if (options != null) {
            startActivityForResult(intent, -1, options);
        } else {
            startActivityForResult(intent, -1);
        }
    }

两个重载方法,都调用了 startActivityForResult 方法,代码如下:

public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,@Nullable Bundle options) {
if (mParent == null) { // mParent 表示这 当现在的Activity 没有父Activity
options = transferSpringboardActivityOptions(options);
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
if (ar != null) {
mMainThread.sendActivityResult(
mToken, mEmbeddedID, requestCode, ar.getResultCode(),
ar.getResultData());
}
if (requestCode >= 0) {
mStartedActivity = true;
}
cancelInputsAndStartExitTransition(options);
} 

....  ignore some code ...

}

在前面说过Instrumentation这个类,每个Activity都持有一个Instrumentation对象的一个引用,当时整个进程中只会存在一个Instrumentation对象,当startActivityForResult方法调用后实际还是调用了mInstrumentation.execStartActivity,mInstrumentation 在Activity的attach方法中初始化。

这里注意 mMainThread 是 ActivityThread 也就是我们常说的主线程,mMainThread.getApplicationThread() ApplicationThread 是ActivityThread 的内部类。

当 mParent != null 时走下面这段代码:

else { if (options != null) { //当现在的Activity有父Activity的时候会调用,但是在startActivityFromChild()内部实际还是调用的mInstrumentation.execStartActivity() mParent.startActivityFromChild(this, intent, requestCode, options); } else { mParent.startActivityFromChild(this, intent, requestCode); } }

Instrumentation 的 execStartActivity 方法,代码实现如下:

public ActivityResult execStartActivity(Context who, IBinder contextThread, IBinder token, Activity target,Intent intent, int requestCode, Bundle options) {
... ignore some code ...
try {
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess(who);
int result = ActivityManager.getService()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, options);
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
throw new RuntimeException("Failure from system", e);
}
return null;
}

所以,当我们程序调用startActivity方法的时候,实际上是调用的Instrumentation 的相关方法。

Instrumentation 可以意为‘仪器’,我们看一下这个类大致包含哪些方法

[图片上传失败...(image-118e35-1522472148194)]

这个类里面的方法大多数和Application和Activity 有关,这个类就是完成了对Application和Activity的初始化和生命周期的工具类,比如我们看一下callActivityOnCreate方法,代码如下:

/**
* Perform calling of an activity's {@link Activity#onCreate} 注意这一句话,调用了Activity的入口函数 onCreate
* method. The default implementation simply calls through to that method.
*
* @param activity The activity being created.
* @param icicle The previously frozen state (or null) to pass through to onCreate().
*/
public void callActivityOnCreate(Activity activity, Bundle icicle) {
prePerformCreate(activity);
activity.performCreate(icicle);
postPerformCreate(activity);
}

再看一下activity.performCreate(icicle);方法

final void performCreate(Bundle icicle) {
restoreHasCurrentPermissionRequest(icicle);
onCreate(icicle);
mActivityTransitionState.readState(icicle);
performCreateCommon();
}

Instrumentation 这个类是很重要的,对Activity的生命周期方法调用根本离不开他,这么重要的类,为什么在开发中没有发现他的轨迹呢?

Instrumentation 可以说是一个大管家,管内不管外,他是老板娘。

老板是谁呢?当然是 ActivityThread .

AMS说:“ActivityThread,你给我暂停一个Activity!”

ActivityThread就说:“没问题!”然后转身和Instrumentation说:“老婆,AMS让暂停一个Activity,我这里忙着呢,你快去帮我把这事办了把~”

于是,Instrumentation就去把事儿搞定了。

所以说,AMS是董事会,负责指挥和调度的,ActivityThread是老板,虽然说家里的事自己说了算,但是需要听从AMS的指挥,而Instrumentation则是老板娘,负责家里的大事小事,但是一般不抛头露面,听一家之主ActivityThread的安排。

我们继续分析 execStartActivity方法,根据这段代码可以看出,启动Activity 是由 ActivityManager.getService().startActivity 方法启动的,这里注意API 26 及26 之后源码有变动。

int result = ActivityManager.getService().startActivity(whoThread, who.getBasePackageName(), intent,intent.resolveTypeIfNeeded(who.getContentResolver()),token, target != null ? target.mEmbeddedID : null,requestCode, 0, null, options);

ActivityManager.getService() 的代码如下:

/**
* @hide
*/
public static IActivityManager getService() {
return IActivityManagerSingleton.get();
}

private static final Singleton<IActivityManager> IActivityManagerSingleton =
new Singleton<IActivityManager>() {
@Override
protected IActivityManager create() {
final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
final IActivityManager am = IActivityManager.Stub.asInterface(b); // 如何实现的呢?
return am;
}
};

IActivityManager.Stub.asInterface(b); 这句代码我找了好久终于在 ActivityManagerNative 类中找到了 代码如下:

public abstract class ActivityManagerNative {
/**
* Cast a Binder object into an activity manager interface, generating
* a proxy if needed.
*
* @deprecated use IActivityManager.Stub.asInterface instead. // 最重要的是这句话   改为使用IActivityManager.Stub.asInterface
*/

static public IActivityManager asInterface(IBinder obj) {
return IActivityManager.Stub.asInterface(obj);
}

static public IActivityManager getDefault() {
return ActivityManager.getService();
}
}

我们在看一下 API 26 之前的ActivityManagerNative源码是如何写的呢?代码如下:

public abstract class ActivityManagerNative extends Binder implements IActivityManager
{
    /**
     *  //最终返回的还是一个ActivityManagerProxy对象
     */
    static public IActivityManager asInterface(IBinder obj) {
        if (obj == null) {
            return null;
        }
        IActivityManager in =
            (IActivityManager)obj.queryLocalInterface(descriptor);
        if (in != null) {
            return in;
        }

//这里面的Binder类型的obj参数会作为ActivityManagerProxy的成员变量保存为mRemote成员变量,负责进行IPC通信
        return new ActivityManagerProxy(obj);
    }

    /**
     *  //从类声明上,我们可以看到ActivityManagerNative是Binder的一个子类,而且实现了IActivityManager接口
     */
    static public IActivityManager getDefault() {
        return gDefault.get();
    }
//通过单例模式获取一个IActivityManager对象,这个对象通过asInterface(b)获得 
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>()
{
protected IActivityManager create()
{
IBinder b = ServiceManager.getService("activity"); 
if (false) {
Log.v("ActivityManager", "default service binder = " + b);
}
IActivityManager am = asInterface(b); 
if (false) {
Log.v("ActivityManager", "default service = " + am);
}
return am;
}
};
}
...ignore some code ...
}

搜得死内 ,asInterface 方法返回的就是ActivityManagerService的远程接口,即ActivityManagerProxy。

我们再看一下 ActivityManagerProxy 方法中的 startActivity() 方法,这里面主要做的事情就是IPC通信,利用 Binder 对象,调用transact(),把所有需要的参数封装成 Parcel对象,向AMS发送数据通信,代码如下:

  public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeStrongBinder(caller != null ? caller.asBinder() : null);
        data.writeString(callingPackage);
        intent.writeToParcel(data, 0);
        data.writeString(resolvedType);
        data.writeStrongBinder(resultTo);
        data.writeString(resultWho);
        data.writeInt(requestCode);
        data.writeInt(startFlags);
        if (profilerInfo != null) {
            data.writeInt(1);
            profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
        } else {
            data.writeInt(0);
        }
        if (options != null) {
            data.writeInt(1);
            options.writeToParcel(data, 0);
        } else {
            data.writeInt(0);
        }
        mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
        reply.readException();
        int result = reply.readInt();
        reply.recycle();
        data.recycle();
        return result;
    }

private IBinder mRemote;
mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);

Binder本质上只是一种底层通信方式,和具体服务没有关系。为了提供具体服务,Server必须提供一套接口函数以便Client通过远程访问使用各种服务。这时通常采用Proxy设计模式:将接口函数定义在一个抽象类中,Server和Client都会以该抽象类为基类实现所有接口函数,所不同的是Server端是真正的功能实现,而Client端是对这些函数远程调用请求的包装。

具体的流程是这样的: 客户端:ActivityManagerProxy =====>Binder驱动=====> ActivityManagerService:服务器

但是!这里Binder通信是单方向的,即从ActivityManagerProxy指向ActivityManagerService的,如果AMS想要通知ActivityThread做一些事情,应该咋办呢?

还是通过Binder通信,不过是换了另外一对,换成了ApplicationThread和ApplicationThreadProxy。

客户端:ApplicationThread <=====Binder驱动<===== ApplicationThreadProxy:服务器

可以看出不管是API 26 还是 API 26 之前的 ,主要做的事情就是IPC通信,利用 Binder 对象,向AMS发送数据通信。

实际上就是调用了AMS 中的startActivity方法。

public final class ActivityManagerService extends ActivityManagerNative
        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback

API 26 AMS 的继承关系也发生了改变

public class ActivityManagerService extends IActivityManager.Stub
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback

两种一对比其实实现都是一样的逻辑。

AMS接收到客户端的请求之后,会如何开启一个Activity?

OK,当我们点击桌面图标调用startActivity,终于把数据和要开启的Activity的请求发送到了AMS,那么AMS到底做了什么呢?

注意!这一块调用的方法链非常之多,如果头脑不够清晰建议休息一下。

AMS收到startActivity的请求之后,会按照如下的方法链进行调用

调用startActivity()

@Override

public final int startActivity(IApplicationThread caller, String callingPackage,

Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,

int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {

return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,

resultWho, requestCode, startFlags, profilerInfo, bOptions,

UserHandle.getCallingUserId());

}

调用startActivityAsUser()

@Override

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) {

...ignore some code...

return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,

resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,

profilerInfo, null, null, options, userId, null, null);

}

在这里又出现了一个新对象ActivityStackSupervisor,通过这个类可以实现对ActivityStack的部分操作。

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, int userId, IActivityContainer iContainer, TaskRecord inTask) {

...ignore some code...

int res = startActivityLocked(caller, intent, resolvedType, aInfo,

voiceSession, voiceInteractor, resultTo, resultWho,

requestCode, callingPid, callingUid, callingPackage,

realCallingPid, realCallingUid, startFlags, options,

componentSpecified, null, container, inTask);

...ignore some code...

}

继续调用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 componentSpecified, ActivityRecord[] outActivity, ActivityContainer container,

TaskRecord inTask) {

err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor,

startFlags, true, options, inTask);

if (err < 0) {

notifyActivityDrawnForKeyguard();

}

return err;

}

调用startActivityUncheckedLocked(),此时要启动的Activity已经通过检验,被认为是一个正当的启动请求。

终于,在这里调用到了ActivityStack的startActivityLocked(ActivityRecord r, boolean newTask,boolean doResume, boolean keepCurTransition, Bundle options)。

ActivityRecord代表的就是要开启的Activity对象,里面分装了很多信息,比如所在的ActivityTask等,如果这是首次打开应用,那么这个Activity会被放到ActivityTask的栈顶,

final int startActivityUncheckedLocked(ActivityRecord r, ActivityRecord sourceRecord,

IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags,

boolean doResume, Bundle options, TaskRecord inTask) {

...ignore some code...

targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);

...ignore some code...

return ActivityManager.START_SUCCESS;

}

调用的是ActivityStack.startActivityLocked()

final void startActivityLocked(ActivityRecord r, boolean newTask,
boolean doResume, boolean keepCurTransition, Bundle options) {
//ActivityRecord中存储的TaskRecord信息
TaskRecord rTask = r.task;

...ignore some code...

//如果不是在新的ActivityTask(也就是TaskRecord)中的话,就找出要运行在的TaskRecord对象
TaskRecord task = null;
if (!newTask) {
boolean startIt = true;
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
task = mTaskHistory.get(taskNdx);
if (task.getTopActivity() == null) {
// task中的所有Activity都结束了
continue;
}

if (task == r.task) {
// 找到了
if (!startIt) {
task.addActivityToTop(r);
r.putInHistory();
mWindowManager.addAppToken(task.mActivities.indexOf(r), r.appToken,
r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen,
(r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0,
r.userId, r.info.configChanges, task.voiceSession != null,
r.mLaunchTaskBehind);
if (VALIDATE_TOKENS) {
validateAppTokensLocked();
}
ActivityOptions.abort(options);
return;
}
break;
} else if (task.numFullscreen > 0) {
startIt = false;
}
}
}

...ignore some code...

// Place a new activity at top of stack, so it is next to interact
// with the user.
task = r.task;
task.addActivityToTop(r);
task.setFrontOfTask();
...ignore some code...
if (doResume) {
mStackSupervisor.resumeTopActivitiesLocked(this, r, options);
}
}

从ActivityStackSupervisor到ActivityStack,又调回ActivityStackSupervisor,!!!!!!!!!!!!!!!!!

淡定…淡定…我知道你也在心里骂娘,世界如此美妙,你却如此暴躁,这样不好,不好…

继续,刚才说到哪里了?咱们一起看下StackSupervisor.resumeTopActivitiesLocked(this, r, options)

boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target,
Bundle targetOptions) {
if (targetStack == null) {
targetStack = getFocusedStack();
}
// Do targetStack first.
boolean result = false;
if (isFrontStack(targetStack)) {
result = targetStack.resumeTopActivityLocked(target, targetOptions);
}

...ignore some code...

return result;
}

又调回ActivityStack去了…

ActivityStack.resumeTopActivityLocked()

final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
if (inResumeTopActivity) {
// Don't even start recursing.
return false;
}
boolean result = false;
try {
// Protect against recursion.
inResumeTopActivity = true;
result = resumeTopActivityInnerLocked(prev, options);
} finally {
inResumeTopActivity = false;
}
return result;
}

咱们坚持住,看一下ActivityStack.resumeTopActivityInnerLocked()到底进行了什么操作

final boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) {

...ignore some code...

//找出还没结束的首个ActivityRecord
ActivityRecord next = topRunningActivityLocked(null);
//如果一个没结束的Activity都没有,就开启Launcher程序
if (next == null) {
ActivityOptions.abort(options);
if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: No more activities go home");
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
// Only resume home if on home display
final int returnTaskType = prevTask == null || !prevTask.isOverHomeStack() ?
HOME_ACTIVITY_TYPE : prevTask.getTaskToReturnTo();
return isOnHomeDisplay() &&mStackSupervisor.resumeHomeStackTask(returnTaskType, prev);
}

//先需要暂停当前的Activity。因为我们是在Lancher中启动mainActivity,所以当前mResumedActivity!=null,调用startPausingLocked()使得Launcher进入Pausing状态
if (mResumedActivity != null) {
pausing |= startPausingLocked(userLeaving, false, true, dontWaitForPause);
if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Pausing " + mResumedActivity);
}
}

在这个方法里,prev.app为记录启动Lancher进程的ProcessRecord,prev.app.thread为Lancher进程的远程调用接口IApplicationThead,所以可以调用prev.app.thread.schedulePauseActivity,到Lancher进程暂停指定Activity。

final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping, boolean resuming,
boolean dontWait) {
if (mPausingActivity != null) {
completePauseLocked(false);
}

...ignore some code...

if (prev.app != null && prev.app.thread != null)
try {
mService.updateUsageStats(prev, false);
prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
userLeaving, prev.configChangeFlags, dontWait);
} catch (Exception e) {
mPausingActivity = null;
mLastPausedActivity = null;
mLastNoHistoryActivity = null;
}
} else {
mPausingActivity = null;
mLastPausedActivity = null;
mLastNoHistoryActivity = null;
}
...ignore some code...
}

在Lancher进程中消息传递,调用ActivityThread.handlePauseActivity(),最终调用ActivityThread.performPauseActivity()暂停指定Activity。接着通过前面所说的Binder通信,通知AMS已经完成暂停的操作。

ActivityManagerNative.getDefault().activityPaused(token).

上面这些调用过程非常复杂,源码中各种条件判断让人眼花缭乱,所以说如果你没记住也没关系,你只要记住这个流程,理解了Android在控制Activity生命周期时是如何操作,以及是通过哪几个关键的类进行操作的就可以了,以后遇到相关的问题之道从哪块下手即可,这些过程我虽然也是撸了一遍,但还是记不清。

image.png

需要注意的代码 app.thread.scheduleLaunchActivity 这个方法

final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
boolean andResume, boolean checkConfig) throws RemoteException {
....................

app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
System.identityHashCode(r), r.info,
// TODO: Have this take the merged configuration instead of separate global and
// override configs.
mergedConfiguration.getGlobalConfiguration(),
mergedConfiguration.getOverrideConfiguration(), r.compat,
r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
r.persistentState, results, newIntents, !andResume,
mService.isNextTransitionForward(), profilerInfo);.
..................

}

app.thread 实际上就是ApplicationThread,最终回到了ApplicationThread 的scheduleLaunchActivity 方法 来启动Activity,我们知道ApplicationThread 是ActivityThread 的内部类

private class ApplicationThread extends IApplicationThread.Stub {
@Override
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
int procState, Bundle state, PersistableBundle persistentState,
List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {

updateProcessState(procState, false);
ActivityClientRecord r = new ActivityClientRecord();
r.token = token;
r.ident = ident;
r.intent = intent;
r.referrer = referrer;
r.voiceInteractor = voiceInteractor;
r.activityInfo = info;
r.compatInfo = compatInfo;
r.state = state;
r.persistentState = persistentState;
r.pendingResults = pendingResults;
r.pendingIntents = pendingNewIntents;
r.startsNotResumed = notResumed;
r.isForward = isForward;
r.profilerInfo = profilerInfo;
r.overrideConfig = overrideConfig;
updatePendingConfiguration(curConfig);
sendMessage(H.LAUNCH_ACTIVITY, r);
}
}

scheduleLaunchActivity 实现方法很简单 发送了一个启动Activity的消息交给Handler处理。

sendMessage 代码如下:

private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
if (DEBUG_MESSAGES) Slog.v(
TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
+ ": " + arg1 + " / " + obj);
Message msg = Message.obtain();
msg.what = what;
msg.obj = obj;
msg.arg1 = arg1;
msg.arg2 = arg2;
if (async) {
msg.setAsynchronous(true);
}
mH.sendMessage(msg);
}

接下来看一下 Handler H 对消息的处理

public void handleMessage(Message msg) {

if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));

switch (msg.what) {

case LAUNCH_ACTIVITY: {

Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");

final ActivityClientRecord r = (ActivityClientRecord) msg.obj;

r.packageInfo = getPackageInfoNoCheck(

r.activityInfo.applicationInfo, r.compatInfo);

handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");

Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

} break;

}

可以看出Activity的启动过程由 ActivityThread handleLaunchActivity 方法实现的,看一下 handleLaunchActivity 的代码如下:

private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {

// If we are getting ready to gc after going to the background, well

// we are back active so skip it.

unscheduleGcIdler();

mSomeActivitiesChanged = true;

if (r.profilerInfo != null) {

mProfiler.setProfiler(r.profilerInfo);

mProfiler.startProfiling();

}

// Make sure we are running with the most recent config.

handleConfigurationChanged(null, null);

if (localLOGV) Slog.v(

TAG, "Handling launch of " + r);

// Initialize before creating the activity

WindowManagerGlobal.initialize();

Activity a = performLaunchActivity(r, customIntent);

if (a != null) {

r.createdConfig = new Configuration(mConfiguration);

reportSizeConfigurations(r);

Bundle oldState = r.state;

handleResumeActivity(r.token, false, r.isForward,

!r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);

if (!r.activity.mFinished && r.startsNotResumed) {

performPauseActivityIfNeeded(r, reason);

if (r.isPreHoneycomb()) {

r.state = oldState;

}

}

} else {

// If there was an error, for any reason, tell the activity manager to stop us.

try {

ActivityManager.getService()

.finishActivity(r.token, Activity.RESULT_CANCELED, null,

Activity.DONT_FINISH_TASK_WITH_ACTIVITY);

} catch (RemoteException ex) {

throw ex.rethrowFromSystemServer();

}

}

}

从上面代码可以看出,performLaunchActivity 方法最终完成了Activity对象的创建和启动过程,并且通过handleLaunchActivity 方法的handleResumeActivity 调用被启动Activity的onResume 这一个生命周期方法。

简单看一下 performLaunchActivity 的代码,做了些什么:

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
//1 从ActivityClientRecord 中获取待启动 Activity的组件信息
ActivityInfo aInfo = r.activityInfo;
if (r.packageInfo == null) {
r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
Context.CONTEXT_INCLUDE_CODE);
}
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);
}

// 2 通过Instrumentation的newActivity 方法使用类加载器创建Activity对象
ContextImpl appContext = createBaseContextForActivity(r);
Activity activity = null;
try {
java.lang.ClassLoader cl = appContext.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
r.intent.prepareToEnterProcess();
if (r.state != null) {
r.state.setClassLoader(cl);
}
} catch (Exception e) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to instantiate activity " + component
+ ": " + e.toString(), e);
}
}

//3 通过LoadedApk 的 makeApplication 方法来尝试创建 Application 对象
Application app = r.packageInfo.makeApplication(false, mInstrumentation);

...........................

appContext.setOuterContext(activity);
// 4 创建ContextImpl 对象并通过Activity的attach方法来完成一些重要数据的初始化
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, window, r.configCallback);

.........................

// 5 调用Activity的生命周期方法
activity.mCalled = false;
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}

..................................

return activity;
}

至此,整个Activity的启动过程完成。

本文转载自:https://www.jianshu.com/p/ae50fca65b8e

天王盖地虎626

天王盖地虎626

粉丝 31
博文 522
码字总数 20708
作品 0
南京
私信 提问
Android深入四大组件(七)Android8.0 根Activity启动过程(后篇)

相关文章 Android深入四大组件系列 Android系统启动系列 Android应用程序进程系列 Android深入解析AMS系列 前言 在几个月前我写了Android深入四大组件(一)应用程序启动过程(前篇)和Andro...

刘望舒
2017/12/25
0
0
Android AOSP基础(五)Android Studio调试系统源码的三种方式

本文首发于微信公众号「刘望舒」 关联系列 Android AOSP基础系列 Android系统启动系列 应用进程启动系列 Android深入四大组件系列 Android深入理解Context系列 Android深入理解JNI系列 Andr...

刘望舒
08/05
0
0
Android深入四大组件(六)Android8.0 根Activity启动过程(前篇)

相关文章 Android深入四大组件系列 Android系统启动系列 Android应用程序进程系列 Android深入解析AMS系列 前言 在几个月前我写了Android深入四大组件(一)应用程序启动过程(前篇)和Andro...

刘望舒
2017/11/27
0
0
Android 进阶学习笔记整理

一.android系统架构图及各层介绍 1. 应用层:应用是用java语言编写的运行在虚拟机上的程序,比如通讯录,日历,电话,短信,浏览器等。 2. 应用框架层:这一层是编写Google发布的核心应用时所...

FunCode
2018/07/22
0
0
Android AOSP基础(二)是时候下载Android9.0源码了

本文首发于微信公众号「刘望舒」 相关系列文章 Android系统启动系列 应用进程启动系列 Android深入四大组件系列 Android深入理解Context系列 Android深入理解JNI系列 Android解析WindowManag...

刘望舒
05/15
0
0

没有更多内容

加载失败,请刷新页面

加载更多

SpringBoot中 集成 redisTemplate 对 Redis 的操作(二)

SpringBoot中 集成 redisTemplate 对 Redis 的操作(二) List 类型的操作 1、 向列表左侧添加数据 Long leftPush = redisTemplate.opsForList().leftPush("name", name); 2、 向列表右......

TcWong
今天
4
0
排序––快速排序(二)

根据排序––快速排序(一)的描述,现准备写一个快速排序的主体框架: 1、首先需要设置一个枢轴元素即setPivot(int i); 2、然后需要与枢轴元素进行比较即int comparePivot(int j); 3、最后...

FAT_mt
昨天
4
0
mysql概览

学习知识,首先要有一个总体的认识。以下为mysql概览 1-架构图 2-Detail csdn |简书 | 头条 | SegmentFault 思否 | 掘金 | 开源中国 |

程序员深夜写bug
昨天
10
0
golang微服务框架go-micro 入门笔记2.2 micro工具之微应用利器micro web

micro web micro 功能非常强大,本文将详细阐述micro web 命令行的功能 阅读本文前你可能需要进行如下知识储备 golang分布式微服务框架go-micro 入门笔记1:搭建go-micro环境, golang微服务框架...

非正式解决方案
昨天
8
0
前端——使用base64编码在页面嵌入图片

因为页面中插入一个图片都要写明图片的路径——相对路径或者绝对路径。而除了具体的网站图片的图片地址,如果是在自己电脑文件夹里的图片,当我们的HTML文件在别人电脑上打开的时候图片则由于...

被毒打的程序猿
昨天
9
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部