相關文章?
[Android View體系(一)視圖坐標系](http://blog.csdn.net/itachi85/article/details/50708391)?
[Android View體系(二)實現View滑動的六種方法](http://blog.csdn.net/itachi85/article/details/50724558)?
[Android View體系(三)屬性動畫](http://blog.csdn.net/itachi85/article/details/49835449)?
[Android View體系(四)從源碼解析Scroller](http://blog.csdn.net/itachi85/article/details/50781845)?
[Android View體系(五)從源碼解析View的事件分發機制](http://blog.csdn.net/itachi85/article/details/50836188)
### 前言
本來這篇是要講View的工作流程的,View的工作流程主要指的measure、layout、draw這三大流程,在講到這三大流程之前我們有必要要先了解下Activity的構成,所以就有了這篇文章。
### 1.從源碼解析Activity的構成
當我們寫Activity時會調用setContentView()方法,來加載布局,來看看setContentView()方法是怎么實現的(Activity.java):
~~~
public void setContentView(@LayoutRes int layoutResID) {
getWindow().setContentView(layoutResID);
initWindowDecorActionBar();
}
~~~
這里調用了getWindow().setContentView(layoutResID),getWindow()指的是什么呢?接著往下看,getWindow()返回mWindow:
~~~
public Window getWindow() {
return mWindow;
}
~~~
在Activity的attach()方法發現mWindow:
~~~
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, String referrer, IVoiceInteractor voiceInteractor) {
attachBaseContext(context);
mFragments.attachHost(null /*parent*/);
mWindow = new PhoneWindow(this);
...省略
}
~~~
原來mWindow指的就是PhoneWindow,PhoneWindow是繼承抽象類Window的,這樣就知道getWindow()得到的是一個PhoneWindow,我們來看看PhoneWindow.java的setContentView()方法(PhoneWindow.java):
~~~
@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.
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 {
mContentParent.addView(view, params);
}
final Callback cb = getCallback();
if (cb != null && !isDestroyed()) {
cb.onContentChanged();
}
}
~~~
在第5行看到了 installDecor()方法,來看看這個方法里寫了什么:
~~~
if (mDecor == null) {
mDecor = generateDecor();
mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
mDecor.setIsRootNamespace(true);
if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
}
}
if (mContentParent == null) {
mContentParent = generateLayout(mDecor);
}
...省略
}
...省略
}
~~~
再接著追蹤看看generateDecor()方法里寫了什么:
~~~
protected DecorView generateDecor() {
return new DecorView(getContext(), -1);
}
~~~
這里創建了一個DecorView,這個DecorView就是Activity中的根View。接著查看DecorView的源碼,發現DecorView是PhoneWindow類的內部類,并且繼承FrameLayout。我們再來看看第10行generateLayout()方法:
~~~
protected ViewGroup generateLayout(DecorView decor) {
...省略
//根據不同的情況加載不同的布局給layoutResource
int layoutResource;
int features = getLocalFeatures();
// System.out.println("Features: 0x" + Integer.toHexString(features));
if ((features & ((1 << FEATURE_LEFT_ICON) | (1 << FEATURE_RIGHT_ICON))) != 0) {
if (mIsFloating) {
TypedValue res = new TypedValue();
getContext().getTheme().resolveAttribute(
com.android.internal.R.attr.dialogTitleIconsDecorLayout, res, true);
layoutResource = res.resourceId;
} else {
layoutResource = com.android.internal.R.layout.screen_title_icons;
}
// XXX Remove this once action bar supports these features.
removeFeature(FEATURE_ACTION_BAR);
// System.out.println("Title Icons!");
} else if ((features & ((1 << FEATURE_PROGRESS) | (1 << FEATURE_INDETERMINATE_PROGRESS))) != 0
&& (features & (1 << FEATURE_ACTION_BAR)) == 0) {
// Special case for a window with only a progress bar (and title).
// XXX Need to have a no-title version of embedded windows.
layoutResource = com.android.internal.R.layout.screen_progress;
// System.out.println("Progress!");
} else if ((features & (1 << FEATURE_CUSTOM_TITLE)) != 0) {
// Special case for a window with a custom title.
// If the window is floating, we need a dialog layout
if (mIsFloating) {
TypedValue res = new TypedValue();
getContext().getTheme().resolveAttribute(
com.android.internal.R.attr.dialogCustomTitleDecorLayout, res, true);
layoutResource = res.resourceId;
} else {
layoutResource = com.android.internal.R.layout.screen_custom_title;
}
// XXX Remove this once action bar supports these features.
removeFeature(FEATURE_ACTION_BAR);
...省略
mDecor.startChanging();
//將layoutResource加載到View中并添加到DecorView中
View in = mLayoutInflater.inflate(layoutResource, null);
decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
...省略
}
~~~
第42行加載layoutResource的布局,來看看其中的一種布局R.layout.screen_title,這個文件在frameworks\base\core\res\res\layout目錄中(screen_title.xml)
~~~
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:fitsSystemWindows="true">
<!-- Popout bar for action modes -->
<ViewStub android:id="@+id/action_mode_bar_stub"
android:inflatedId="@+id/action_mode_bar"
android:layout="@layout/action_mode_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="?attr/actionBarTheme" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="?android:attr/windowTitleSize"
style="?android:attr/windowTitleBackgroundStyle">
<TextView android:id="@android:id/title"
style="?android:attr/windowTitleStyle"
android:background="@null"
android:fadingEdge="horizontal"
android:gravity="center_vertical"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
<FrameLayout android:id="@android:id/content"
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:foregroundGravity="fill_horizontal|top"
android:foreground="?android:attr/windowContentOverlay" />
</LinearLayout>
~~~
上面的ViewStub是用來顯示ActionBar的,下面的兩個FrameLayout,一個是title用來顯示標題,一個是content用來顯示內容。
### 2.圖解Activity的構成
看到如上的源碼大家就知道了一個Activity包含一個window對象,這個對象是由PhoneWindow來實現的,PhoneWindow將DecorView做為整個應用窗口的根View,而這個DecorView又將屏幕劃分為兩個區域一個是TitleView一個是ContentView,而我們平常做應用所寫的布局正是展示在ContentView中的。?

- 前言
- Camera源碼分析(android2.2)
- Android開機啟動流程說明
- android應用程序管理機制
- MediaPlayer框架概述(一)
- MediaPlayer框架概述(二)
- Android MediaPlayer+Stagefright框架(音頻)圖解
- Stagefright框架解讀(—)音視頻Playback流程
- Android mediaRecorder框架簡述(一)
- Android mediaRecorder框架簡述(二)
- Android IntentService淺談以及源碼分析
- Android多線程(二)AsyncTask源碼分析
- Android View體系(五)從源碼解析View的事件分發機制
- Android View體系(六)從源碼解析Activity的構成