想来自己毕业也有将近半年,做android开发也有半年时间,这段时间学到了很多android基础的东西,自定义view、view事件分发流程、view滑动冲突、四大组件等等,但是总感觉自己还是对android理解的很浅,每当看到网上大神写的源码分析博客我就非常头疼,这些都是些什么鬼啊??? 也许这就是自己和大厂的程序员区别所在吧,有时候心里会偷偷问自己,为什么别人可以你不可以?
所以今天这篇博客自己也算是酝酿了几个月的成果。
四大组件之一Activity,我们用的非常多了。我们都知道Activity生命周期无非就是onCreate()、onStart(),onResume()等,但是我们知道Activity对象是什么时候创建的吗?它在什么时候调用onCreate()什么调用onResume()呢??
所有的Acticity启动都是通过ActivityThread类来启动,它会调用handleLaunchActivity()方法来创建activity对象
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
2875 unscheduleGcIdler();
2876 mSomeActivitiesChanged = true;
2877
2878 if (r.profilerInfo != null) {
2879 mProfiler.setProfiler(r.profilerInfo);
2880 mProfiler.startProfiling();
2881 }
2882
2884 handleConfigurationChanged(null, null);
2885
2886 if (localLOGV) Slog.v(
2887 TAG, "Handling launch of " + r);
2888
2890 WindowManagerGlobal.initialize();
2891 //在handleLaunchActivity()内部调用performLaunchActivity()方法,它返回的是当前activity对象
2892 Activity a = performLaunchActivity(r, customIntent);
2893
2894 if (a != null) {
2895 r.createdConfig = new Configuration(mConfiguration);
2896 reportSizeConfigurations(r);
2897 Bundle oldState = r.state;
2898 handleResumeActivity(r.token, false, r.isForward,
2899 !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
2900
2901 if (!r.activity.mFinished && r.startsNotResumed) {
2902
2916 if (r.isPreHoneycomb()) {
2917 r.state = oldState;
2918 }
2919 }
2920 } else {
2922 try {
2923 ActivityManager.getService()
2924 .finishActivity(r.token, Activity.RESULT_CANCELED, null,
2925 Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
2926 } catch (RemoteException ex) {
2927 throw ex.rethrowFromSystemServer();
2928 }
2929 }
2930 }
handleLaunchActivity()方法内部调用performLaunchActivity()方法,它返回的是当前activity对象,进入performLaunchActivity看下源码,里面有这么三段代码
Activity activity = null;
2705 //创建activity对象
2706 try {
2707 java.lang.ClassLoader cl = appContext.getClassLoader();
2708 activity = mInstrumentation.newActivity(
2709 cl, component.getClassName(), r.intent);
2710 StrictMode.incrementExpectedActivityCount(activity.getClass());
2711 r.intent.setExtrasClassLoader(cl);
2712 r.intent.prepareToEnterProcess();
2713 if (r.state != null) {
2714 r.state.setClassLoader(cl);
2715 }
2716 } catch (Exception e) {
2717 if (!mInstrumentation.onException(activity, e)) {
2718 throw new RuntimeException(
2719 "Unable to instantiate activity " + component
2720 + ": " + e.toString(), e);
2721 }
2742 //创建PhoneWindow对象
2743 Window window = null;
2744 if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
2745 window = r.mPendingRemoveWindow;
2746 r.mPendingRemoveWindow = null;
2747 r.mPendingRemoveWindowManager = null;
2748 }
2766 if (r.isPersistable()) {
2767 //最后会调用activity的oncreate()
2768 mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
2769 } else {
2770 mInstrumentation.callActivityOnCreate(activity, r.state);
2771 }
第一段代码:通过反射创建activity对象
第二段代码:创建window对象
第三段代码:调用callActivityOnCreate()
我们继续进入callActivityOnCreate()看源码
1224 public void callActivityOnCreate(Activity activity, Bundle icicle,
1225 PersistableBundle persistentState) {
1226 prePerformCreate(activity);
1227 activity.performCreate(icicle, persistentState);
1228 postPerformCreate(activity);
1229 }
callActivityOnCreate中调用了activity.performCreate()方法,继续进入performCreate()
6980 final void performCreate(Bundle icicle, PersistableBundle persistentState) {
6981 restoreHasCurrentPermissionRequest(icicle);
6982 onCreate(icicle, persistentState);
6983 mActivityTransitionState.readState(icicle);
6984 performCreateCommon();
6985 }
6986
进入performCreate()方法后你会发现我们进入到了Activity类,它是我们所有activity的父类,performCreate中调用了oncreate()方法。到此你应该知道我们的oncreate()是什么时候被调用了吧???
1.handleLaunchActivity()中调用performLaunchActivity(),它返回是我们的activity对象实例
2.performLaunchActivity()中创建activity对象、创建window对象,并且调用callActivityOnCreate()
3.callActivityOnCreate()中调用activity的performCreate()
4.performCreate()调用oncreate()
现在我们知道了activity、window对象是怎么被创建的与及oncreate()怎么被调用的。现在我们又有疑问,oncreate中的setContentView()它是怎么工作的???
接下来我们来看setContentView()的源码
2689 public void setContentView(View view, ViewGroup.LayoutParams params) {
2690 getWindow().setContentView(view, params);
2691 initWindowDecorActionBar();
2692 }
我们看到它执行了这一句代码:
getWindow().setContentView(view, params);
getWindow()从字面意思我们估计是获取我们的窗口对象(上文在performLaunchActivity()中创建的window)
911 public Window getWindow() {
912 return mWindow;
913 }
getWindow()返回的是一个Window 对象,而Window又是一个抽象类,它只有一个实现类PhoneWindow。所以getWindow()返回的是一个PhoneWindow()对象,所以我们到PhoneWindow中查看源码:
433 @Override
434 public void setContentView(View view, ViewGroup.LayoutParams params) {
435 // Note: FEATURE_CONTENT_TRANSITIONS may be set in the process of installing the window
436 // decor, when theme attributes and the like are crystalized. Do not check the feature
437 // before this happens.
438 if (mContentParent == null) {
439 installDecor();
440 } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
441 mContentParent.removeAllViews();
442 }
443
444 if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
445 view.setLayoutParams(params);
446 final Scene newScene = new Scene(mContentParent, view);
447 transitionTo(newScene);
448 } else {
449 mContentParent.addView(view, params);
450 }
451 mContentParent.requestApplyInsets();
452 final Callback cb = getCallback();
453 if (cb != null && !isDestroyed()) {
454 cb.onContentChanged();
455 }
456 mContentParentExplicitlySet = true;
457 }
在PhoneWindow的setContentView()中,438行处调用了 installDecor() ,我们进入 installDecor() 看源码
2641 if (mDecor == null) {
2642 mDecor = generateDecor(-1);
2643 mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
2644 mDecor.setIsRootNamespace(true);
2645 if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
2646 mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
2647 }
2648 } else {
2649 mDecor.setWindow(this);
2650 }
installDecor()中又调用了generateDecor(),generateDecor()源码:
2287 protected DecorView generateDecor(int featureId) {
2288 // System process doesn't have application context and in that case we need to directly use
2289 // the context we have. Otherwise we want the application context, so we don't cling to the
2290 // activity.
2291 Context context;
2292 if (mUseDecorContext) {
2293 Context applicationContext = getContext().getApplicationContext();
2294 if (applicationContext == null) {
2295 context = getContext();
2296 } else {
2297 context = new DecorContext(applicationContext, getContext().getResources());
2298 if (mTheme != -1) {
2299 context.setTheme(mTheme);
2300 }
2301 }
2302 } else {
2303 context = getContext();
2304 }
2305 return new DecorView(context, featureId, this, getAttributes());
2306 }
我们看到最后一行代码:return 一个DecorView对象,DecorView正是我们的顶层布局
因此我们可以总结得到:setContentView()过程就是获取phoneWindow对象,phoneWindow对象调用setContentView(),setContentView()中会去创建DecorView对象,最后将我们的布局交给DecorView。
看一下activity的总体结构:
我们的布局最后会被DecorView加入到ContentParent当中。
现在我们知道了Activity的启动过程,oncreate调用时期,与及setContentView()最终会作用到哪里,但是我们还不知什么时候我们view开始绘制,我们回到ActivityThread的 handleLaunchActivity()方法
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
2875 unscheduleGcIdler();
2876 mSomeActivitiesChanged = true;
2877
2878 if (r.profilerInfo != null) {
2879 mProfiler.setProfiler(r.profilerInfo);
2880 mProfiler.startProfiling();
2881 }
2882
2884 handleConfigurationChanged(null, null);
2885
2886 if (localLOGV) Slog.v(
2887 TAG, "Handling launch of " + r);
2888
2890 WindowManagerGlobal.initialize();
2891 //在handleLaunchActivity()内部调用performLaunchActivity()方法,它返回的是当前activity对象
2892 Activity a = performLaunchActivity(r, customIntent);
2893
2894 if (a != null) {
2895 r.createdConfig = new Configuration(mConfiguration);
2896 reportSizeConfigurations(r);
2897 Bundle oldState = r.state;
2898 //注意这句代码,view的绘制从这开始
2898 handleResumeActivity(r.token, false, r.isForward,
2899 !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
2900
2901 if (!r.activity.mFinished && r.startsNotResumed) {
2902
2916 if (r.isPreHoneycomb()) {
2917 r.state = oldState;
2918 }
2919 }
2920 } else {
2922 try {
2923 ActivityManager.getService()
2924 .finishActivity(r.token, Activity.RESULT_CANCELED, null,
2925 Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
2926 } catch (RemoteException ex) {
2927 throw ex.rethrowFromSystemServer();
2928 }
2929 }
2930 }
我们可以看到执行完performLaunchActivity()后调用了handleResumeActivity(),handleResumeActivity源码
3710 if (r.window == null && !a.mFinished && willBeVisible) {
3710 //获取phoneWindow对象
3711 r.window = r.activity.getWindow();
3711 //获取DecorView对象
3712 View decor = r.window.getDecorView();
3712 //DecorView设置为不可见
3713 decor.setVisibility(View.INVISIBLE);
3713 //获取WindowManager对象
3714 ViewManager wm = a.getWindowManager();
3715 WindowManager.LayoutParams l = r.window.getAttributes();
3716 a.mDecor = decor;
3717 l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
3718 l.softInputMode |= forwardBit;
3719 if (r.mPreserveWindow) {
3720 a.mWindowAdded = true;
3721 r.mPreserveWindow = false;
3726 ViewRootImpl impl = decor.getViewRootImpl();
3727 if (impl != null) {
3728 impl.notifyChildRebuilt();
3729 }
3730 }
3731 if (a.mVisibleFromClient) {
3732 if (!a.mWindowAdded) {
3733 a.mWindowAdded = true;
3733 //DecorView添加到WindowManager中
3734 wm.addView(decor, l);
3735 } else {
3736
3740 a.onWindowAttributesChanged(l);
3741 }
3742 }
3743
3744
3747 } else if (!willBeVisible) {
3748 if (localLOGV) Slog.v(
3749 TAG, "Launch " + r + " mStartedActivity set");
3750 r.hideForNow = true;
3751 }
通过源码可以看出调用了getWindowManager()返回一个WindowManager对象,而WindowManager又是抽象类,它的子类是WindowManagerImpl,源码最后调用了 wm.addView(decor, l);,wm是一个WindowManagerImpl对象,再看WindowManagerImpl源码:
89 @Override
90 public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
91 applyDefaultToken(params);
92 mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
93 }
WindowManagerImpl的 addView()又调用了 mGlobal.addView(),mGlobal源码:
public void addView(View view, ViewGroup.LayoutParams params,Display display, Window parentWindow) {
......
ViewRootImpl root;
View panelParentView = null;
......
root = new ViewRootImpl(view.getContext(), display);
view.setLayoutParams(wparams);
mViews.add(view);
mRoots.add(root);
mParams.add(wparams);
}
// do this last because it fires off messages to start doing things
try {
root.setView(view, wparams, panelParentView);
} catch (RuntimeException e) {
}
在该方法中首先会实例化一个ViewRootImpl,在调用ViewRootImpl的setView方法将DecorView加载到Window中,在setView方法中会调用window的addToDisplay方法,将DecorView显示出来,最后调用scheduleTraversals()发送一个message(这个message被Loop取出给ViewRoot中的handleMessage里的一个方法),这个方法是就performTraversals(),也就是启动了绘画流程,这个方法里面会分别调用measure、layout、draw。
最后推荐一下这个在线看源码的网站:android源码