您的位置:首页 > 移动开发 > Android开发

Android Activity启动过程简读 <1>

2016-04-13 20:10 525 查看
平时工作中经常会谈一些Activity启动过程,周期之类的话题.其实整体单纯来说还是比较简单.

<1> : Activity的启动都是从startActivity(...)开始.

<2> : 对比Activity的周期中涉及到几个阶段,如果onCreate,onResume...,当发现程序调用这些方法时,第一时间想到的是framework的Activity管理根据状态在回调这些方法.

<3> : 谈及第二点,比较Activity和Fragement在生命周期中,会发现Fragement包含一个attach方法,而Activity似乎没有,用过Fragment的attach方法的都知道它的好,Activity实际也是有的,隐藏着,当然实际上个人觉得提供给开发者用处不大.但是这个在framework里面却非常的重要的.

<4> : 涉及的代码(主要的部分):framework/base/core/java/android/app下的Activity,ActivityThread,Instrumentation,然后就是framework/base/services/java/com/android/server/am目录下,重点是ActivityStack和ActivityManagerService.分别编译生成framework.jar和services.jar.

<5> : 创建内容,前面谈到蓝牙服务的时候,顺便说了很多其他服务也是在SystemServer中创建的,所以ActivityManagerService也是在系统Server中创建的.com.android.server.SystemServer中的init2的线程run中.framework很多地方调用这个服务的方式:

(ActivityManagerService)ActivityManagerNative.getDefault().***

<6> : 当启动一个app时,相应创建一个ActivityThread进行管理所有的Activity,而这些Activity的运行状态是靠对应的ActivityRecord记录的,如果是APP第一个Activity,那么会同时创建一个process进程,进程默认名是APP的包名,当然APP也可以在主配置xml中自行安排Activity进程,同一个进程的Activity,进程只会创建一次,但是ActivityThread数量应该是和Activity一一对应的.注意前面<3> 的回调在管理处是先处理对应的Application的周期回调Activity,不知这句话是否说准了.

<7> : 回调生命周期各方法是通过Handle消息机制完成的.在ActivityThread中处理的.

<8> : ActivityThread和ActivityManagerService频繁的互相调用对方,是非常繁琐的,但是线索还是比较清晰的.

好了,开始从Activity类的startActivity方法开始:

@Override
public void startActivity(Intent intent, Bundle options) {
if (options != null) {
startActivityForResult(intent, -1, options);
} else {
// Note we want to go through this call for compatibility with
// applications that may have overridden the method.
startActivityForResult(intent, -1);
}
}

跟着下去,关键的几句:

mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);

然后到Instruction类中:

public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Fragment target,
Intent intent, int requestCode, Bundle options) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
if (mActivityMonitors != null) {
synchronized (mSync) {
final int N = mActivityMonitors.size();
for (int i=0; i<N; i++) {
final ActivityMonitor am = mActivityMonitors.get(i);
if (am.match(who, null, intent)) {
am.mHits++;
if (am.isBlocking()) {
return requestCode >= 0 ? am.getResult() : null;
}
break;
}
}
}
}
try {
intent.setAllowFds(false);
intent.migrateExtraStreamToClipData();
int result = ActivityManagerNative.getDefault()
.startActivity(whoThread, intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mWho : null,
requestCode, 0, null, null, options);
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
}
return null;
}


根据上面的几条中说明的,下面调用ActivityManagerService类.

int result = ActivityManagerNative.getDefault()
.startActivity(whoThread, intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mWho : null,
requestCode, 0, null, null, options);

进入ActivityManagerService类中:

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

public final int startActivityAsUser(IApplicationThread caller,
Intent intent, String resolvedType, IBinder resultTo,
String resultWho, int requestCode, int startFlags,
String profileFile, ParcelFileDescriptor profileFd, Bundle options, int userId) {
enforceNotIsolatedCaller("startActivity");
userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
false, true, "startActivity", null);
return mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
resultTo, resultWho, requestCode, startFlags, profileFile, profileFd,
null, null, options, userId);
}


其中mMainStack是ActivityStack类对应的startActivityMayWait方法中:

int res = startActivityLocked(caller, intent, resolvedType,
aInfo, resultTo, resultWho, requestCode, callingPid, callingUid,
startFlags, options, componentSpecified, null);


然后继续:

private final void startActivityLocked(ActivityRecord r, boolean newTask,
boolean doResume, boolean keepCurTransition, Bundle options) {
final int NH = mHistory.size();


在这个方法中打出log,会发现NH>1始终成立,这个NH是获得mHistory Activity是否在后台和后台数量,因为桌面Launcher总是会启动,所以NH第一个一般是Launcher,doResume也是为true.mHostory是ArrayList保存的所有ActivityRecord,这个也是没创建一个Activity对应创建一个,做好Activity状态等记录.

if (doResume) {
resumeTopActivityLocked(null);
}

看到这个方法最后面:

startSpecificActivityLocked(next, true, true);

看到这个地方就越来越明显了,

private final void startSpecificActivityLocked(ActivityRecord r,
boolean andResume, boolean checkConfig) {
// Is this activity's application already running?
ProcessRecord app = mService.getProcessRecordLocked(r.processName,
r.info.applicationInfo.uid);

if (r.launchTime == 0) {
r.launchTime = SystemClock.uptimeMillis();
if (mInitialStartTime == 0) {
mInitialStartTime = r.launchTime;
}
} else if (mInitialStartTime == 0) {
mInitialStartTime = SystemClock.uptimeMillis();
}

if (app != null && app.thread != null) {
try {
app.addPackage(r.info.packageName);
realStartActivityLocked(r, app, andResume, checkConfig);
return;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting activity "
+ r.intent.getComponent().flattenToShortString(), e);
}

// If a dead object exception was thrown -- fall through to
// restart the application.
}

mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
"activity", r.intent.getComponent(), false, false);
}


看到最后startProcessLocked方法.这个在ActivityManagerService类中,直接看里面的重点:

// Start the process.  It will either succeed and return a result containing
// the PID of the new process, or else throw a RuntimeException.
Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",
app.processName, uid, uid, gids, debugFlags, mountExternal,
app.info.targetSdkVersion, null, null);

这个非常重要,可以说是新的Activity的启动,上面程序创建ActivityThread进程,从而且确定创建一个新的Activity,那么就可以查看ActivityThread类了.

直接看他的main:

public static void main(String[] args) {
SamplingProfilerIntegration.start();

// CloseGuard defaults to true and can be quite spammy.  We
// disable it here, but selectively enable it later (via
// StrictMode) on debug builds, but using DropBox, not logs.
CloseGuard.setEnabled(false);

Environment.initForCurrentUser();

// Set the reporter for event logging in libcore
EventLogger.setReporter(new EventLoggingReporter());

Process.setArgV0("<pre-initialized>");

Looper.prepareMainLooper();

ActivityThread thread = new ActivityThread();
thread.attach(false);

if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}

AsyncTask.init();

if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}

Looper.loop();

throw new RuntimeException("Main thread loop unexpectedly exited");
}

注重看下面:

ActivityThread thread = new ActivityThread();
thread.attach(false);

同样在ActivityThread类中看他的attach方法:

RuntimeInit.setApplicationObject(mAppThread.asBinder());
IActivityManager mgr = ActivityManagerNative.getDefault();
try {
mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {
// Ignore
}

调用了ActivityManagerService中的attachApplication方法.

public final void attachApplication(IApplicationThread thread) {
synchronized (this) {
int callingPid = Binder.getCallingPid();
final long origId = Binder.clearCallingIdentity();
attachApplicationLocked(thread, callingPid);
Binder.restoreCallingIdentity(origId);
}
}


继续跟踪attachApplicationLocked方法,这个里面要仔细看,不然还真容易走眼:

mMainStack.realStartActivityLocked(hr, app, true, true)

看来又回到ActivityStack中:

app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
System.identityHashCode(r), r.info,
new Configuration(mService.mConfiguration),
r.compat, r.icicle, results, newIntents, !andResume,
mService.isNextTransitionForward(), profileFile, profileFd,
profileAutoStop);

又到ActivityThread中:直接看下面的

queueOrSendMessage(H.LAUNCH_ACTIVITY, r);

终于到了发送Handle message了

case LAUNCH_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
ActivityClientRecord r = (ActivityClientRecord)msg.obj;

r.packageInfo = getPackageInfoNoCheck(
r.activityInfo.applicationInfo, r.compatInfo);
handleLaunchActivity(r, null);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

然后:

Activity a = performLaunchActivity(r, customIntent);


然后继续:

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
// System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");

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);
}

Activity activity = null;
try {
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
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);
}
}

try {
Application app = r.packageInfo.makeApplication(false, mInstrumentation);

if (localLOGV) Slog.v(TAG, "Performing launch of " + r);
if (localLOGV) Slog.v(
TAG, r + ": app=" + app
+ ", appName=" + app.getPackageName()
+ ", pkg=" + r.packageInfo.getPackageName()
+ ", comp=" + r.intent.getComponent().toShortString()
+ ", dir=" + r.packageInfo.getAppDir());

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

终于看到activity的第一个生命周期attach方法了.

上面一路还有很多判断条件,可以自行根据自己想了解的部分,参考上面的思路跟踪,应该没什么问题,打log.



后面的继续... ...
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: