摘要:我们了解到activity是如何启动的,启动后下一步就应该是渲染activity的视图了,我们都知道一个activity张上面样子 取决于我们在onCreat方法了调用了setContentView,那我们来分析下他吧

setContentView

activity里重载了很多个setContentView方法,我们只分析一个就行

1
2
3
4
5
6
7
8
public void setContentView(View view) {
getWindow().setContentView(view);
initWindowDecorActionBar();
}
public Window getWindow() {
return mWindow;
}

可以看到 其实是调用了mWindow的setContentView 方法,window我们都知道,他是一个屏幕的最低层,那我们点进去接着往下看

1
2
3
4
5
6
7
8
9
10
11
12
public abstract class Window {
/** Flag for the "options panel" feature. This is enabled by default. */
public static final int FEATURE_OPTIONS_PANEL = 0;
/** Flag for the "no title" feature, turning off the title at the top
* of the screen. */
public static final int FEATURE_NO_TITLE = 1;
/** Flag for the progress indicator feature */
public static final int FEATURE_PROGRESS = 2;
/** Flag for having an icon on the left side of th
........

咦,这window原来是个抽象类,那他到底是个什么类型,我们在回到activity看看他是如何初始化的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
final void attach(Context context, ActivityThread aThread,
Instrumentation instr, IBinder token, int ident,
Application application, Intent intent, ActivityInfo info,
CharSequence title, Activity parent, String id,
NonConfigurationInstances lastNonConfigurationInstances,
Configuration config, IVoiceInteractor voiceInteractor) {
attachBaseContext(context);
mFragments.attachActivity(this, mContainer, null);
//这里初始化了 window
mWindow = PolicyManager.makeNewWindow(this);
mWindow.setCallback(this);
mWindow.setOnWindowDismissedCallback(this);
mWindow.getLayoutInflater().setPrivateFactory(this);
if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
mWindow.setSoftInputMode(info.softInputMode);
}
if (info.uiOptions != 0) {
mWindow.setUiOptions(info.uiOptions);
}

Window是什么?

该方法在ActivityThread的performLaunchActivity方法被调用,就是创建一个activity的方法。 这回找到了 mWindow 是如何初始化的,但是还是看不出他什么个什么 实例化对象,而且又出来一个新东西 PolicyManager.makeNewWindow(this);的PolicyManager 是个什么玩意?
我没开一探究竟 \frameworks\base\core\java\com\android\internal\policy\PolicyManager

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
public final class PolicyManager {
//会通过这个 反射创建 IPolicy实例
private static final String POLICY_IMPL_CLASS_NAME =
"com.android.internal.policy.impl.Policy";
private static final IPolicy sPolicy;
static {
// Pull in the actual implementation of the policy at run-time
try {
Class policyClass = Class.forName(POLICY_IMPL_CLASS_NAME);
sPolicy = (IPolicy)policyClass.newInstance();
} catch (ClassNotFoundException ex) {
throw new RuntimeException(
POLICY_IMPL_CLASS_NAME + " could not be loaded", ex);
} catch (InstantiationException ex) {
throw new RuntimeException(
POLICY_IMPL_CLASS_NAME + " could not be instantiated", ex);
} catch (IllegalAccessException ex) {
throw new RuntimeException(
POLICY_IMPL_CLASS_NAME + " could not be instantiated", ex);
}
}
// Cannot instantiate this class
private PolicyManager() {}
// The static methods to spawn new policy-specific objects
public static Window makeNewWindow(Context context) {
return sPolicy.makeNewWindow(context);
}
public static LayoutInflater makeNewLayoutInflater(Context context) {
return sPolicy.makeNewLayoutInflater(context);
}
public static WindowManagerPolicy makeNewWindowManager() {
return sPolicy.makeNewWindowManager();
}
public static FallbackEventHandler makeNewFallbackEventHandler(Context context) {
return sPolicy.makeNewFallbackEventHandler(context);
}
}

嗯,这个类就这么几行代码 里面有个关键的东西sPolicy 继续走(注意:前方高能你将进入水下的冰山了)
根据上面的 POLICY_IMPL_CLASS_NAME 获取到了Policy 我没来看一下他

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
public class Policy implements IPolicy {
private static final String TAG = "PhonePolicy";
private static final String[] preload_classes = {
"com.android.internal.policy.impl.PhoneLayoutInflater",
"com.android.internal.policy.impl.PhoneWindow",
"com.android.internal.policy.impl.PhoneWindow$1",
"com.android.internal.policy.impl.PhoneWindow$DialogMenuCallback",
"com.android.internal.policy.impl.PhoneWindow$DecorView",
"com.android.internal.policy.impl.PhoneWindow$PanelFeatureState",
"com.android.internal.policy.impl.PhoneWindow$PanelFeatureState$SavedState",
};
static {
// For performance reasons, preload some policy specific classes when
// the policy gets loaded.
for (String s : preload_classes) {
try {
Class.forName(s);
} catch (ClassNotFoundException ex) {
Log.e(TAG, "Could not preload class for phone policy: " + s);
}
}
}
//返回了 Window
public Window makeNewWindow(Context context) {
return new PhoneWindow(context);
}
public LayoutInflater makeNewLayoutInflater(Context context) {
return new PhoneLayoutInflater(context);
}
public WindowManagerPolicy makeNewWindowManager() {
return new PhoneWindowManager();
}
public FallbackEventHandler makeNewFallbackEventHandler(Context context) {
return new PhoneFallbackEventHandler(context);
}

代码也不多 但是可以看到 makeNewWindow 里干了什么,他new 了一个 PhoneWindow 还有 makeNewWindowManager 里new 了一个PhoneWindowManager
这下我们知道 activity里的getWindow 到底获取到了个 什么东西.

继续setContentView(windows的方法)

刚才在看activity的时候已经知道 其setContentView方法 其实调用的window的setContentView方法 ,现在我们也知道了这个 window其实是一个 PhoneWindow,来上代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
private DecorView mDecor;
private ViewGroup mContentParent;
private ViewGroup mContentRoot;
@Override
public void setContentView(View view) {
setContentView(view, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
}
@Override
public void setContentView(View view, ViewGroup.LayoutParams params) {
// Note: FEATURE_CONTENT_TRANSITIONS may be set in the process of installing the window
// decor, when theme attributes and the like are crystalized. Do not check the feature
// before this happens.
//判断 mContentParent 没有则创建
if (mContentParent == null) {
installDecor();
} else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
mContentParent.removeAllViews();
}
if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
view.setLayoutParams(params);
final Scene newScene = new Scene(mContentParent, view);
transitionTo(newScene);
} else {
//将传进来的view添加到 mContentParent
mContentParent.addView(view, params);
}
final Callback cb = getCallback();
if (cb != null && !isDestroyed()) {
cb.onContentChanged();
}
}

其实这里就干了两件事

  • 判断 mContentParent 没有则创建
  • 然后把传进来的view添加到 mContentParent

我们再来看看 installDecor 方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
private void installDecor() {
if (mDecor == null) {
//创建 DecorView
mDecor = generateDecor();
mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
mDecor.setIsRootNamespace(true);
if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
}
}
if (mContentParent == null) {
//通过 DecorView 得到mContentParent
mContentParent = generateLayout(mDecor);
。。。。。。。其他赋值操作
}
}

继续看 generateDecor 和generateLayout 函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
//generateDecor 很简单 就是 new 了个DecorView
protected DecorView generateDecor() {
return new DecorView(getContext(), -1);
}
protected ViewGroup generateLayout(DecorView decor) {
// Apply data from current theme.
TypedArray a = getWindowStyle();
if (false) {
System.out.println("From style:");
String s = "Attrs:";
for (int i = 0; i < R.styleable.Window.length; i++) {
s = s + " " + Integer.toHexString(R.styleable.Window[i]) + "="
+ a.getString(i);
}
System.out.println(s);
}
mIsFloating = a.getBoolean(R.styleable.Window_windowIsFloating, false);
int flagsToUpdate = (FLAG_LAYOUT_IN_SCREEN|FLAG_LAYOUT_INSET_DECOR)
& (~getForcedWindowFlags());
if (mIsFloating) {
setLayout(WRAP_CONTENT, WRAP_CONTENT);
setFlags(0, flagsToUpdate);
} else {
.....一堆 赋值操作
mDecor.startChanging();
//标题栏
View in = mLayoutInflater.inflate(layoutResource, null);
decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
mContentRoot = (ViewGroup) in;
//contentParent 由findViewById 返回
ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
if (contentParent == null) {
throw new RuntimeException("Window couldn't find content container view");
}
.......
return contentParent;
}

generateDecor 很简单 就是 new 了个DecorView ,而DecorView 实际上就是个 Framelayout.
generateLayout 函数很长 差不多300多行 我们只挑重点的看

  • 主要是给DecorView 添加了标题栏
  • 通过findViewById 获取到 contentParent ,这个findViewById 其实是调用了DecorView的这个findViewById
    如图

总结

  • setContentView 其实是调用window的setContentView
  • window 是通过PolicyManager 获取到的PhoneWindow对象
  • window 的setContentView 创建了DecorView (Framelayout)
  • window 的setContentView 创建了DecorView
  • 通过DecorView 创建了contentParent
  • 把setContentView传过来的View add到contentParent 上

关于contentParent 的addView(view, params)方法

下回再说吧,又该睡了