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很多地方调用这个服务的方式:
<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);
}
}
跟着下去,关键的几句:
然后到Instruction类中:
根据上面的几条中说明的,下面调用ActivityManagerService类.
进入ActivityManagerService类中:
其中mMainStack是ActivityStack类对应的startActivityMayWait方法中:
然后继续:
在这个方法中打出log,会发现NH>1始终成立,这个NH是获得mHistory Activity是否在后台和后台数量,因为桌面Launcher总是会启动,所以NH第一个一般是Launcher,doResume也是为true.mHostory是ArrayList保存的所有ActivityRecord,这个也是没创建一个Activity对应创建一个,做好Activity状态等记录.
看到这个方法最后面:
看到这个地方就越来越明显了,
看到最后startProcessLocked方法.这个在ActivityManagerService类中,直接看里面的重点:
这个非常重要,可以说是新的Activity的启动,上面程序创建ActivityThread进程,从而且确定创建一个新的Activity,那么就可以查看ActivityThread类了.
直接看他的main:
注重看下面:
同样在ActivityThread类中看他的attach方法:
调用了ActivityManagerService中的attachApplication方法.
继续跟踪attachApplicationLocked方法,这个里面要仔细看,不然还真容易走眼:
看来又回到ActivityStack中:
又到ActivityThread中:直接看下面的
终于到了发送Handle message了
然后:
然后继续:
终于看到activity的第一个生命周期attach方法了.
上面一路还有很多判断条件,可以自行根据自己想了解的部分,参考上面的思路跟踪,应该没什么问题,打log.
后面的继续... ...
<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.
后面的继续... ...
相关文章推荐
- 【Android】在activity中使用menu菜单
- android 之activity生命周期
- 解决Mac上android设备不显示的问题
- 【Android控件】呼吸效果的动画
- 深入理解Android中的View
- Android客户端性能优化(魅族资深工程师毫无保留奉献)
- Android中Parcelable接口的应用
- Android中service讲解
- Android开源项目分类汇总
- [Android Studio系列(三)]Android Studio 编译、同步慢的解决方法
- android事件分发
- Android 带checkbox的listView 实现多选,全选,反选,删除
- 【Android】Toast控件使用
- Android百度地图定位收索取周边在列表中展示并选择
- 【Android】Mainifest文件手动添加Activity
- Android使用ViewDragHelper实现仿QQ6.0侧滑界面(一)
- 自定义ANDROID中EDITTEXT中的HINT文本的大小
- Android 从启动到程序运行发生的事情
- Android 事件流详解之View事件分发
- android stdio 1