源码分析结论

由以上2.1~2.6对源码的分析,可以得到以下结论:

3.1 Activity、Window和View的依赖关系:


3.2 setContentView()执行的序列图:

Activity展示的其实是PhoneWindow上的内容。那么其实 setContentView 实际上是调用的 PhonwWindow的setContentView。可以看出Window是做为中介者连接了Activity和View。

3.3.Activity的视图框架结构(http://www.amjmh.com/v/)


3.4 解释一下DecorView的布局资源的加载逻辑,features变量是怎么来的:

再观察generateLaout()的实现如下:

protected ViewGroup generateLayout(DecorView decor) {
...
int layoutResource;
int features = getLocalFeatures(); //获取的是mLocalFeatures值
//下面是一堆用feastures值来判断改用哪个布局文件的逻辑
if ((features & (1 << FEATURE_SWIPE_TO_DISMISS)) != 0) {
layoutResource = R.layout.screen_swipe_dismiss;
setCloseOnSwipeEnabled(true);
} else if ((features & ((1 << FEATURE_LEFT_ICON) | (1 << FEATURE_RIGHT_ICON))) != 0) {
if (mIsFloating) {
TypedValue res = new TypedValue();
getContext().getTheme().resolveAttribute( R.attr.dialogTitleIconsDecorLayout, res, true);
layoutResource = res.resourceId;
} else {
layoutResource = R.layout.screen_title_icons;
}
removeFeature(FEATURE_ACTION_BAR);
}
...
mDecor.startChanging();
mDecor.onResourcesLoaded(mLayoutInflater, layoutResource);
ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
...
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
那么,mLocalFeatures的值是怎么来的?直接搜索mLocalFeatures被赋值的地方,发现是通过getDefaultFeatures()方法拿到的,但是这个只是拿到默认的features值,这是不够的。反推,上面都是位操作,我们要搜索mFeatures和mLocalFeaures的位操作地方了,源码里面用一个int值代表一堆标记位的事情也不少了。果然,发现,是在PhonwWindow的requestFeature()中设置的标记位:
public boolean requestFeature(int featureId) {
if (mContentParentExplicitlySet) {
throw new AndroidRuntimeException("requestFeature() must be called before adding content");
}
final int features = getFeatures();
final int newFeatures = features | (1 << featureId);
if ((newFeatures & (1 << FEATURE_CUSTOM_TITLE)) != 0 &&
(newFeatures & ~CUSTOM_TITLE_COMPATIBLE_FEATURES) != 0) {
throw new AndroidRuntimeException(
"You cannot combine custom titles with other title features");
}
...
//Window的requestFeature()会将featureId通过按位或运算记录到mFeatures变量中
return super.requestFeature(featureId);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
这样也能解释的通了,为什么在Activity中使用requestFeature()要在setContentView()前调用了,以为这个值是给Activity的DecorView选择加载那种样式的布局文件用的。如果在setContentView之后调用,这个时候PhoneWindow::generateLayout(DecorView)已经执行完成了,并不会生效。

 

posted on 2019-09-04 17:12  激流勇进1  阅读(137)  评论(0编辑  收藏  举报