从activity的创建到销毁,会走onCreate()、onStart()、onResume()、onPause()、onStop()、onDestory()等生命周期,对于开发者来说充分理解activity的生命周期可以在适当的回调方法中进行业务逻辑处理;不过这要说的并不是onCreate()、onStart()、onResume()、onPause()、onStop()、onDestory()等生命周期,而是从点击一个app图标这些生命周期是如何走的,界面是如何展示给用户的;说到这些,肯定会提到ActivityThread类。
ActivityThread:它是一个管理应用程序进程中主线程的执行、调度和执行活动,根据活动管理器的请求在其上广播和其他操作。
在用户点击app Launcher 图标时,会去调用ActivityThread类中的main方法,这也是应用程序的主入口;
public static void main(String[] args) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
SamplingProfilerIntegration.start();
CloseGuard.setEnabled(false);
Environment.initForCurrentUser();
EventLogger.setReporter(new EventLoggingReporter());
final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
TrustedCertificateStore.setDefaultUserDirectory(configDir);
Process.setArgV0("<pre-initialized>");
//实例化准备一个Looper
Looper.prepareMainLooper();
//实例化一个ActivityThread对象
ActivityThread thread = new ActivityThread();
//调用attach方法
thread.attach(false);
//实例化handler对象
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
// End of event ActivityThreadMain.
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
//调用loop()进行消息轮询
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
在main方法中会实例化一个ActivityThread对象,在ActivityThread类中有一个mH成员变量,其实就是一个handler,在handler的handlerMessage回调中发现activity生命周期的方法在那里被调用,其实activity的生命周期都是通过handler消息来管理的,根据handler消息的类型会去调用handleLaunchActivity方法;
从流程图中知道会在handleLaunchActivity方法中调用performLaunchActivity方法,并返回一个Activity实例;
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
......
// 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
WindowManagerGlobal.initialize();
Activity a = performLaunchActivity(r, customIntent);
......
}
跟着流程图和源码看看activity在performLaunchActivity方法中是如何创建的,
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
// System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");
ActivityInfo aInfo = r.activityInfo;
//获取apk包信息
if (r.packageInfo == null) {
r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
Context.CONTEXT_INCLUDE_CODE);
}
//通过ComponentName和intent也可以启动一个activity
//Intent intent=new Intent();
//ComponentName componentName=ComponentName.createRelative(MainActivity.this,SecondActivity.class);
// intent.setComponent(componentName);
//startActivity(intent);
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创建一个上下文
ContextImpl appContext = createBaseContextForActivity(r);
Activity activity = null;
try {
//通过反射实例化一个activity对象
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);
}
}
try {
......
if (activity != null) {
.......
appContext.setOuterContext(activity);
//调用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);
......
activity.mCalled = false;
//调用Instrumentation中的callActivityOnCreate方法,
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
......
r.activity = activity;
r.stopped = true;
if (!r.activity.mFinished) {
//判断当前activity是否finish,如果没有finish就会调用activity中的performStart方法
activity.performStart();
r.stopped = false;
}
......
//r.token就是一个IBinder对象,将IBinder为key,ActivityClientRecord对象为value缓存在map集合中
mActivities.put(r.token, r);
......
return activity;
}
通过调用Instrumentation中的newActivity就实例化好了一个activity,看下activity在里面是如何被实例化的;
public Activity newActivity(ClassLoader cl, String className,
Intent intent)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
//获取到应用程序的包名
String pkg = intent != null && intent.getComponent() != null
? intent.getComponent().getPackageName() : null;
return getFactory(pkg).instantiateActivity(cl, className, intent);
}
public @NonNull Activity instantiateActivity(@NonNull ClassLoader cl, @NonNull String className,
@Nullable Intent intent)
throws InstantiationException, IllegalAccessException, ClassNotFoundException {
return (Activity) cl.loadClass(className).newInstance();
}
通过传入的ClassLoader和应用程序包名实例化一个activity,这样子通过反射就实例化好一个activity,就会去调用attch方法,在attch方法中会绑定activity的上下文,初始化PhoneWindow、获取当前线程、setWindowManager等各种操作,而在Instrumentation的callActivityOnCreate方法中会根据实例化好的activity去调用它里面的performCreate方法;
public void callActivityOnCreate(Activity activity, Bundle icicle) {
prePerformCreate(activity);
activity.performCreate(icicle);
postPerformCreate(activity);
}
在activity的performCreate方法中就会看到调用了onCreate方法;
final void performCreate(Bundle icicle) {
restoreHasCurrentPermissionRequest(icicle);
onCreate(icicle);
mActivityTransitionState.readState(icicle);
performCreateCommon();
}
调用完onCreate方法后,接着会根据实例化好的activity,并且当前activity没有finish,就会去调用自己的performStart()方法;
final void performStart() {
......
//通过传入当前的activity在Instrumentation的callActivityOnStart方法中调用activity自己的onStart方法
mInstrumentation.callActivityOnStart(this);
......
mActivityTransitionState.enterReady(this);
}
public void callActivityOnStart(Activity activity) {
activity.onStart();
}
这样子activity的onCreate、onStart方法就走了;接着看onResume,先去看handleResumeActivity
final void handleResumeActivity(IBinder token,
boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
//根据activity创建时缓存的IBinder获取对应的ActivityClientRecord对象
ActivityClientRecord r = mActivities.get(token);
//检查和更新生命周期
if (!checkAndUpdateLifecycleSeq(seq, r, "resumeActivity")) {
return;
}
// If we are getting ready to gc after going to the background, well
// we are back active so skip it.
unscheduleGcIdler();
mSomeActivitiesChanged = true;
// TODO Push resumeArgs into the activity for consideration
//需要注意performResumeActivity方法的调用
r = performResumeActivity(token, clearHide, reason);
if (r != null) {
//这里的ActivityClientRecord对象不为null
//获取缓存中的activity实例
final Activity a = r.activity;
if (localLOGV) Slog.v(
TAG, "Resume " + r + " started activity: " +
a.mStartedActivity + ", hideForNow: " + r.hideForNow
+ ", finished: " + a.mFinished);
final int forwardBit = isForward ?
WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION : 0;
// If the window hasn't yet been added to the window manager,
// and this guy didn't finish itself or start another activity,
// then go ahead and add the window.
boolean willBeVisible = !a.mStartedActivity;
if (!willBeVisible) {
try {
willBeVisible = ActivityManager.getService().willActivityBeVisible(
a.getActivityToken());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
if (r.window == null && !a.mFinished && willBeVisible) {
//获取activity attch初始化时的window对象
r.window = r.activity.getWindow();
//获取window对象中的DecorView
View decor = r.window.getDecorView();
//设置DecorView为不可见
decor.setVisibility(View.INVISIBLE);
//获取activity中对应的ViewManager
ViewManager wm = a.getWindowManager();
WindowManager.LayoutParams l = r.window.getAttributes();
a.mDecor = decor;
//给window设置参数
l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
l.softInputMode |= forwardBit;
if (r.mPreserveWindow) {
a.mWindowAdded = true;
r.mPreserveWindow = false;
// Normally the ViewRoot sets up callbacks with the Activity
// in addView->ViewRootImpl#setView. If we are instead reusing
// the decor view we have to notify the view root that the
// callbacks may have changed.
ViewRootImpl impl = decor.getViewRootImpl();
if (impl != null) {
impl.notifyChildRebuilt();
}
}
if (a.mVisibleFromClient) {
if (!a.mWindowAdded) {
a.mWindowAdded = true;
//将设置好的DecorView通过ViewManager添加到布局中
wm.addView(decor, l);
} else {
// The activity will get a callback for this {@link LayoutParams} change
// earlier. However, at that time the decor will not be set (this is set
// in this method), so no action will be taken. This call ensures the
// callback occurs with the decor set.
a.onWindowAttributesChanged(l);
}
}
// If the window has already been added, but during resume
// we started another activity, then don't yet make the
// window visible.
} else if (!willBeVisible) {
if (localLOGV) Slog.v(
TAG, "Launch " + r + " mStartedActivity set");
r.hideForNow = true;
}
// Get rid of anything left hanging around.
cleanUpPendingRemoveWindows(r, false /* force */);
// The window is now visible if it has been added, we are not
// simply finishing, and we are not starting another activity.
if (!r.activity.mFinished && willBeVisible
&& r.activity.mDecor != null && !r.hideForNow) {
if (r.newConfig != null) {
performConfigurationChangedForActivity(r, r.newConfig);
if (DEBUG_CONFIGURATION) Slog.v(TAG, "Resuming activity "
+ r.activityInfo.name + " with newConfig " + r.activity.mCurrentConfig);
r.newConfig = null;
}
if (localLOGV) Slog.v(TAG, "Resuming " + r + " with isForward="
+ isForward);
WindowManager.LayoutParams l = r.window.getAttributes();
if ((l.softInputMode
& WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION)
!= forwardBit) {
l.softInputMode = (l.softInputMode
& (~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION))
| forwardBit;
if (r.activity.mVisibleFromClient) {
ViewManager wm = a.getWindowManager();
View decor = r.window.getDecorView();
//通过ViewManager更新布局的摆放
wm.updateViewLayout(decor, l);
}
}
r.activity.mVisibleFromServer = true;
mNumVisibleActivities++;
if (r.activity.mVisibleFromClient) {
r.activity.makeVisible();
}
}
if (!r.onlyLocalRequest) {
r.nextIdle = mNewActivities;
mNewActivities = r;
if (localLOGV) Slog.v(
TAG, "Scheduling idle handler for " + r);
Looper.myQueue().addIdleHandler(new Idler());
}
r.onlyLocalRequest = false;
// Tell the activity manager we have resumed.
if (reallyResume) {
try {
ActivityManager.getService().activityResumed(token);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
} else {
// If an exception was thrown when trying to resume, then
// just end this activity.
try {
ActivityManager.getService()
.finishActivity(token, Activity.RESULT_CANCELED, null,
Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
}
一进入handleResumeActivity方法就去调用了performResumeActivity方法,
public final ActivityClientRecord performResumeActivity(IBinder token,
boolean clearHide, String reason) {
//通过缓存的IBinder获取ActivityClientRecord对象
ActivityClientRecord r = mActivities.get(token);
if (localLOGV) Slog.v(TAG, "Performing resume of " + r
+ " finished=" + r.activity.mFinished);
if (r != null && !r.activity.mFinished) {
//这里的ActivityClientRecord 对象不为空且当前activity也没有finish掉
......
//调用performResume
r.activity.performResume();
......
}
return r;
}
final void performResume() {
//这里也会先调用performRestart方法,
performRestart();
......
mInstrumentation.callActivityOnResume(this);
......
}
和onStart的流程一样,在performResume方法中还是通过Instrumentation中的callActivityOnResume方法利用传入的当前activity,去调用自己的onResume方法;
public void callActivityOnResume(Activity activity) {
activity.mResumed = true;
activity.onResume();
if (mActivityMonitors != null) {
synchronized (mSync) {
final int N = mActivityMonitors.size();
for (int i=0; i<N; i++) {
final ActivityMonitor am = mActivityMonitors.get(i);
am.match(activity, activity, activity.getIntent());
}
}
}
}
不过不同的是,在调用onResume的同时会接着在handleResumeActivity方法中根据activity创建时缓存的对象获取Window、DecorView、ViewManager等实例,并进行参数设置,将设置好参数的view通过ViewManager添加到布局中,也是在onResume生命周中,将布局和view绘制渲染完毕,添加到布局中展示给用户;onResume走完就是onPause,在handlePauseActivity方法中和handleResumeActivity一样,也是根据缓存获取对应的实例对象,判断检查和更新生命周期,调用performPauseActivity方法;
private void handlePauseActivity(IBinder token, boolean finished,
boolean userLeaving, int configChanges, boolean dontReport, int seq) {
ActivityClientRecord r = mActivities.get(token);
if (DEBUG_ORDER) Slog.d(TAG, "handlePauseActivity " + r + ", seq: " + seq);
if (!checkAndUpdateLifecycleSeq(seq, r, "pauseActivity")) {
return;
}
if (r != null) {
//Slog.v(TAG, "userLeaving=" + userLeaving + " handling pause of " + r);
if (userLeaving) {
performUserLeavingActivity(r);
}
r.activity.mConfigChangeFlags |= configChanges;
//注意performPauseActivity的调用
performPauseActivity(token, finished, r.isPreHoneycomb(), "handlePauseActivity");
// Make sure any pending writes are now committed.
if (r.isPreHoneycomb()) {
QueuedWork.waitToFinish();
}
// Tell the activity manager we have paused.
if (!dontReport) {
try {
ActivityManager.getService().activityPaused(token);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
mSomeActivitiesChanged = true;
}
}
在performPauseActivity中利用重载调用的是多一个参数的performPauseActivity方法;
final Bundle performPauseActivity(IBinder token, boolean finished,
boolean saveState, String reason) {
ActivityClientRecord r = mActivities.get(token);
return r != null ? performPauseActivity(r, finished, saveState, reason) : null;
}
这样就只能去看多一个参数的performPauseActivity方法逻辑了;
final Bundle performPauseActivity(ActivityClientRecord r, boolean finished,
boolean saveState, String reason) {
//finished这个参数上面传入的是tr
if (r.paused) {
//走到这里activity还没有finish
if (r.activity.mFinished) {
// If we are finishing, we won't call onResume() in certain cases.
// So here we likewise don't want to call onPause() if the activity
// isn't resumed.
return null;
}
RuntimeException e = new RuntimeException(
"Performing pause of activity that is not resumed: "
+ r.intent.getComponent().toShortString());
Slog.e(TAG, e.getMessage(), e);
}
if (finished) {
//改变activity finish的状态
r.activity.mFinished = true;
}
// Next have the activity save its current state and managed dialogs...
if (!r.activity.mFinished && saveState) {
callCallActivityOnSaveInstanceState(r);
}
//在该方法中会调用Instrumentation中的callActivityOnPause方法
performPauseActivityIfNeeded(r, reason);
// Notify any outstanding on paused listeners
//定义一个OnActivityPausedListener 集合
ArrayList<OnActivityPausedListener> listeners;
synchronized (mOnPauseListeners) {
//将当前onPause的activity中mOnPauseListeners中移除并将移除返回的数据赋值给listeners
listeners = mOnPauseListeners.remove(r.activity);
}
int size = (listeners != null ? listeners.size() : 0);
for (int i = 0; i < size; i++) {
//遍历listeners集合
listeners.get(i).onPaused(r.activity);
}
return !r.activity.mFinished && saveState ? r.state : null;
}
剩下的就会onCreate的调用走向差不多了;
public void callActivityOnPause(Activity activity) {
activity.performPause();
}
handleStopActivity和handlePauseActivity差不多,这里就不写了,自己可以在ActivityThread类中慢慢看,就接着看handleDestroyActivity方法;handleDestroyActivity在调用onDestory的逻辑走向和之前那些一样的,这里就只说下当activity调用onDestory后页面、页面上的view、activity实例的处理;
private void handleDestroyActivity(IBinder token, boolean finishing,
int configChanges, boolean getNonConfigInstance) {
//一样调用performDestroyActivity 在performDestroyActivity方法中会调用Instrumentation的
//callActivityOnDestroy方法,接着调用activity中的onDestory方法
ActivityClientRecord r = performDestroyActivity(token, finishing,
configChanges, getNonConfigInstance);
if (r != null) {
//移除activity中的window对象,在cleanUpPendingRemoveWindows方法中,会将window移除调用将window对象置为null
cleanUpPendingRemoveWindows(r, finishing);
//获取对应的windowManager实例
WindowManager wm = r.activity.getWindowManager();
//获取DecorView
View v = r.activity.mDecor;
if (v != null) {
if (r.activity.mVisibleFromServer) {
mNumVisibleActivities--;
}
IBinder wtoken = v.getWindowToken();
if (r.activity.mWindowAdded) {
if (r.mPreserveWindow) {
// Hold off on removing this until the new activity's
// window is being added.
r.mPendingRemoveWindow = r.window;
r.mPendingRemoveWindowManager = wm;
// We can only keep the part of the view hierarchy that we control,
// everything else must be removed, because it might not be able to
// behave properly when activity is relaunching.
//将window上的view清除掉
r.window.clearContentView();
} else {
//移除window上的view
wm.removeViewImmediate(v);
}
}
if (wtoken != null && r.mPendingRemoveWindow == null) {
WindowManagerGlobal.getInstance().closeAll(wtoken,
r.activity.getClass().getName(), "Activity");
} else if (r.mPendingRemoveWindow != null) {
// We're preserving only one window, others should be closed so app views
// will be detached before the final tear down. It should be done now because
// some components (e.g. WebView) rely on detach callbacks to perform receiver
// unregister and other cleanup.
WindowManagerGlobal.getInstance().closeAllExceptView(token, v,
r.activity.getClass().getName(), "Activity");
}
//移除完view后将DecorView置为null
r.activity.mDecor = null;
}
if (r.mPendingRemoveWindow == null) {
// If we are delaying the removal of the activity window, then
// we can't clean up all windows here. Note that we can't do
// so later either, which means any windows that aren't closed
// by the app will leak. Well we try to warning them a lot
// about leaking windows, because that is a bug, so if they are
// using this recreate facility then they get to live with leaks.
WindowManagerGlobal.getInstance().closeAll(token,
r.activity.getClass().getName(), "Activity");
}
// Mocked out contexts won't be participating in the normal
// process lifecycle, but if we're running with a proper
// ApplicationContext we need to have it tear down things
// cleanly.
Context c = r.activity.getBaseContext();
if (c instanceof ContextImpl) {
((ContextImpl) c).scheduleFinalCleanup(
r.activity.getClass().getName(), "Activity");
}
}
if (finishing) {
try {
ActivityManager.getService().activityDestroyed(token);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
mSomeActivitiesChanged = true;
}
通过上面知道activity调用onDestory后,只是将window上的view进行移除,并将DecorView置为null,并没有将当前的activity实例置为null,所以activity调用onDestory后,页面销毁了,但是activity实例一直在内存中,等待gc的回收,如果内存中的activity实例还被持有,就会造成内存泄露,这是开发中需要注意的。
总结:
1.activity的生命周期是通过handler消息来控制的;
2.activity的实例创建是通过反射来实现的;
3.在activity onResume生命周期后,才将布局view绘制添加到系统布局中并显示给用户;
4.在activity onDestory生命周期后,只是将window、window中的view,DecorView移除并置为null,并没有将activity实例置为null,activity实例仍然在内存中,如果在gc时还有持有该activity的引用就会造成内存泄露,也就是说activity onDestory后只是页面的销毁,并不代表当前activity实例的销毁。