Activityレイアウトロードプロセスソース分析(I)
77701 ワード
最近Androidソースを読むと、新大陸を発見したような感じがします.以前はAndroidの知識に触れていたが、ソースコードを読むうちに、明るくなってきた.先日、2編のブログActivity起動プロセスソース分析(応用中)とActivity起動プロセスソース分析(Launcher中)を書き終えましたが、今日はActivityレイアウトロードプロセスを書きたいと思っています.実は、熱いうちに鉄を打って、この知識を整理したいと思っています.
整理を開始する前に、次のような概念を理解する必要があります. Window:ウィンドウを表す抽象クラスです.Androidシステムのインタフェースも、ウィンドウの形で存在します. PhoneWindow:Windowクラスの具体的な実装クラスであり、Activityでのレイアウトロードロジックは主にこのような中で完了します. WindowManager:Windowの管理クラスで、Windowの追加、更新、削除を管理しています. WindowManagerService(WMS):システムウィンドウ管理サービスクラスであり、システムの様々なWindowを具体的に管理する. DecorView:WindowのトップレベルのViewで、主に各種のViewを搭載しています.
一、Activityレイアウトロード分析
整理を開始する前に、次のような概念を理解する必要があります.
一、Activityレイアウトロード分析
Activityレイアウトの設定は、主にActivityのonCreate()でsetContentView()メソッドを呼び出すことを知っています.次に、このメソッドを見てみましょう.
public void setContentView(int layoutResID) {
getWindow().setContentView(layoutResID);//
initActionBar();
}
ここでは主にgetWindow()を呼び出す.setContentView()メソッドでは、ActivityのgetWindow()を見てみましょう. public Window getWindow() {
return mWindow;
}
このことからmWindowはActivityの属性変数であることがわかり、前述のActivity起動プロセスの紹介では、Activity起動前にattach()が呼び出されることを知っていましたが、このmWindowはattach初期化時に付与されたもので、Activityのattachソースコードを見てみましょう 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) {
attachBaseContext(context);
mFragments.attachActivity(this);
mWindow = PolicyManager.makeNewWindow(this);//
......
mUiThread = Thread.currentThread();
mMainThread = aThread;
mInstrumentation = instr;
mToken = token;
mIdent = ident;
mApplication = application;
mIntent = intent;
mComponent = intent.getComponent();
mActivityInfo = info;
mTitle = title;
mParent = parent;
mEmbeddedID = id;
mLastNonConfigurationInstances = lastNonConfigurationInstances;
mWindow.setWindowManager(null, mToken, mComponent.flattenToString(),
(info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
if (mParent != null) {
mWindow.setContainer(mParent.getWindow());
}
mWindowManager = mWindow.getWindowManager();
mCurrentConfig = config;
}
ここではPolicyManagerに注目してみましょうmakeNewWindow(this)メソッド、Windowを作成するには、PolicyManagerクラスを見てみましょうpublic final class PolicyManager {
private static final String POLICY_IMPL_CLASS_NAME =
"com.android.internal.policy.impl.Policy";
private static final IPolicy sPolicy;
static {
try {
Class policyClass = Class.forName(POLICY_IMPL_CLASS_NAME);
sPolicy = (IPolicy)policyClass.newInstance();// Policy
} 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);
}
}
public static Window makeNewWindow(Context context) {
return sPolicy.makeNewWindow(context); //
}
.......
}
以上から明らかなように,ここでは主に反射によりPolicyを初期化し,その後,PolicyのmakeNewWindow()メソッドを設計モードにおける氏置換原則を用いて呼び出し,Policyにおけるメソッドを引き続き見る.public class Policy implements IPolicy {
........
public PhoneWindow makeNewWindow(Context context) {
return new PhoneWindow(context);//
}
......
}
mWindowは実際にはPhoneWindowであり、ActivityでgetWindow()であることがわかります.setContentView()メソッドとは、PhoneWindowのsetContentViewメソッドを呼び出すことですので、PhoneWindowのsetContentView()メソッドを見てみましょう @Override
public void setContentView(int layoutResID) {
if (mContentParent == null){
installDecor();//1.
} else {
mContentParent.removeAllViews();
}
mLayoutInflater.inflate(layoutResID, mContentParent);//2.
final Callback cb = getCallback();
if (cb != null && !isDestroyed()) {
cb.onContentChanged();
}
}
注釈2から、レイアウトパディングmLayoutInflaterがmContentParentにレイアウト内容を入力していることを知っていますが、mContentParentはView Groupで、どのように値を付けているのでしょうか.ここで注釈1を見てみましょう.mContentParentが空の場合、装飾器が取り付けられます.phoneWindowのinstallDecor()メソッドを見てみましょう. private void installDecor() {
if (mDecor == null) {
mDecor = generateDecor();//1.
mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
mDecor.setIsRootNamespace(true);
}
if (mContentParent == null) {
mContentParent = generateLayout(mDecor);//2. ViewGroup
mDecor.makeOptionalFitsSystemWindows();
mTitleView = (TextView)findViewById(com.android.internal.R.id.title);
if (mTitleView != null) {
if ((getLocalFeatures() & (1 << FEATURE_NO_TITLE)) != 0) {
.......
} else {
mTitleView.setText(mTitle);// Activity title
}
} else {
mActionBar = (ActionBarView) findViewById(com.android.internal.R.id.action_bar);
if (mActionBar != null) {
.......mActionBar
}
}
}
}
まず、注釈1のデコレーションの生成方法generateDecor()を見てみましょう. protected DecorView generateDecor() {
return new DecorView(getContext(), -1);
}
ここでは主に装飾器DecorViewの初期化です.DecorViewのソースコードを見てみましょう. private final class DecorView extends FrameLayout implements RootViewSurfaceTaker {
......
public DecorView(Context context, int featureId) {
super(context);
mFeatureId = featureId;
}
.......
DecorViewクラスには内容が含まれていますが、ここでは説明しません.DecorViewはPhoneWindowの内部クラスであり、DecorViewはFrameLayoutに継承され、RootView Surface Takerインタフェースを実現していることを知っておくだけです.次に、mContentParentの生成、すなわちgenerateLayout(mDecor)メソッドについて説明します. protected ViewGroup generateLayout(DecorView decor) {
.......// window
// Inflate the window decor.
int layoutResource;
int features = getLocalFeatures();
// Activity feature
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;
}
removeFeature(FEATURE_ACTION_BAR);
} else if ((features & ((1 << FEATURE_PROGRESS) | (1 << FEATURE_INDETERMINATE_PROGRESS))) != 0
&& (features & (1 << FEATURE_ACTION_BAR)) == 0) {
//
layoutResource = com.android.internal.R.layout.screen_progress;
} else if ((features & (1 << FEATURE_CUSTOM_TITLE)) != 0) {
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;
}
removeFeature(FEATURE_ACTION_BAR);
} else if ((features & (1 << FEATURE_NO_TITLE)) == 0) {
// Titile
if (mIsFloating) {
TypedValue res = new TypedValue();
getContext().getTheme().resolveAttribute(
com.android.internal.R.attr.dialogTitleDecorLayout, res, true);
layoutResource = res.resourceId;
} else if ((features & (1 << FEATURE_ACTION_BAR)) != 0) {
if ((features & (1 << FEATURE_ACTION_BAR_OVERLAY)) != 0) {
layoutResource = com.android.internal.R.layout.screen_action_bar_overlay;
} else {
layoutResource = com.android.internal.R.layout.screen_action_bar;
}
} else {
layoutResource = com.android.internal.R.layout.screen_title;
}
} else if ((features & (1 << FEATURE_ACTION_MODE_OVERLAY)) != 0) {
layoutResource = com.android.internal.R.layout.screen_simple_overlay_action_mode;
} else {
layoutResource = com.android.internal.R.layout.screen_simple;//1.
}
mDecor.startChanging();
View in = mLayoutInflater.inflate(layoutResource, null);
decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));//2. View View
ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);//3. Activity ViewGroup
......
}
mDecor.finishChanging();
return contentParent;
}
ここでは、システムのデフォルトのいくつかのActivityのヘッダレイアウトxmlファイルを見てみましょう.レイアウトファイルのソースコードの位置はandroid 4です.1.1_r 1frameworksbasecoreresreslayout、2つのファイルを選んでみましょう.
最初のscreen_title.xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:fitsSystemWindows="true">
<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" />
<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>
2つ目はscreen_simple.xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:orientation="vertical">
<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" />
<FrameLayout
android:id="@android:id/content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:foregroundInsidePadding="false"
android:foregroundGravity="fill_horizontal|top"
android:foreground="?android:attr/windowContentOverlay" />
</LinearLayout>
比較すると、この2つのレイアウトファイルには@android:id/contentという共通のidを持つFrameLayoutがありますが、これはActivityレイアウトの充填容器です.また,この2つのレイアウトの親レイアウトはいずれも線形レイアウトLinearLayoutであり,方向は垂直であることが分かった.これは,Activityコンテンツレイアウトが一般的にステータスバーの下のモードであることを検証した.次のコードを見てみましょう View in = mLayoutInflater.inflate(layoutResource, null);
decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));//2. View View
ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);//3. Activity ViewGroup
ここでは、アクセラレータにシステムレイアウトViewを追加し、システムレイアウトViewからActivity充填コンテンツのコンテナView Groupを取得します.ここでID_ANDROID_CONTENTはcomです.android.internal.R.id.contentは、(View Group)findView ById(ID_ANDROID_CONTENT)によって、レイアウトファイルのFrameLayout、すなわちActivityコンテンツがレイアウトのView Groupを埋め込むことを取得する.これでPhoneWindowのsetContentViewメソッドに戻ります @Override
public void setContentView(int layoutResID) {
if (mContentParent == null) {
installDecor();
} else {
mContentParent.removeAllViews();
}
mLayoutInflater.inflate(layoutResID, mContentParent);//
final Callback cb = getCallback();
if (cb != null && !isDestroyed()) {
cb.onContentChanged();
}
}
mContentParentで値を割り当てた後、レイアウトフィラーmLayoutInflaterのinflate()メソッドを使用して、Activityのレイアウトファイルをデザイナに追加しました.しかし、現在ではアクセサリDecorViewにActivityレイアウトがあるようですが、いつWindowに追加されたのでしょうか.ここではActivityの起動プロセスを理解する必要があります.Activityの起動プロセスの最後のステップでActivity ThreadのhandleLaunchActivity()メソッドが実行されます.次に、このメソッドを分析し続けます.private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
.......
Activity a = performLaunchActivity(r, customIntent);//1. Activity
if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
Bundle oldState = r.state;
handleResumeActivity(r.token, false, r.isForward);//2. Activity onResume
.......
} else {
.......
}
}
注記1では、Activityのインスタンスが確立され、Activityライフサイクルのattach()およびonCreate()メソッドが実行される.setContentView()もonCreate()メソッドで呼び出されていることを知っていますので、このときActivityレイアウトファイルの内容はすでにデザイナDecorViewに読み込まれています.次にDecorViewとWindowを関連付けるので、handleResumeActivity()メソッドを引き続き見てみましょう. final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward) {
// If we are getting ready to gc after going to the background, well
// we are back active so skip it.
unscheduleGcIdler();
ActivityClientRecord r = performResumeActivity(token, clearHide);//1. Activity onResume
if (r != null) {
final Activity a = r.activity;
........
boolean willBeVisible = !a.mStartedActivity;
if (!willBeVisible) {
try {
willBeVisible = ActivityManagerNative.getDefault().willActivityBeVisible(a.getActivityToken());//2.Activity
} catch (RemoteException e) {
}
}
if (r.window == null && !a.mFinished && willBeVisible) {
r.window = r.activity.getWindow();
View decor = r.window.getDecorView();
decor.setVisibility(View.INVISIBLE);
ViewManager wm = a.getWindowManager();
WindowManager.LayoutParams l = r.window.getAttributes();
a.mDecor = decor;
l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
l.softInputMode |= forwardBit;
if (a.mVisibleFromClient) {
a.mWindowAdded = true;
wm.addView(decor, l);//3. WindowManager DecorView Window, Window,Activity 。
}
} else if (!willBeVisible) {
r.hideForNow = true;
}
cleanUpPendingRemoveWindows(r);
if (!r.activity.mFinished && willBeVisible&& r.activity.mDecor != null && !r.hideForNow) {
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();
wm.updateViewLayout(decor, l);//4. DecorView, Activity
}
}
r.activity.mVisibleFromServer = true;
mNumVisibleActivities++;
if (r.activity.mVisibleFromClient) {
r.activity.makeVisible();
}
}
.......
} else {
.......
}
}
注記1でperformResumeActivity(token,clearHide)メソッドを呼び出すのは、実際にはactivityライフサイクルを呼び出すonResume()メソッドです.注記2では、Binderによるプロセス間通信により、Activity Management ServiceでwillActivity BeVisible()を呼び出してActivityを表示する制御スイッチを取得することで、注記3でWindowManagerによってデザイナDecorViewをWindowに追加し、その後、関連するViewの描画プロセスを呼び出すというレイアウト付きActivityがロードされる.
ここまで、Activityレイアウトのロードプロセスは整理済みです.
注:ソースコードはandroid-4.1.1_を採用r 1バージョンでは、ソースコードをダウンロードして自分でプロセスを行うことをお勧めします.これにより、より理解が深まります.
二、参考文書
Binder通信メカニズムの原理解析
Activity起動フローソース分析(応用中)
Activity起動フローソース分析(Launcher)
public void setContentView(int layoutResID) {
getWindow().setContentView(layoutResID);//
initActionBar();
}
public Window getWindow() {
return 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) {
attachBaseContext(context);
mFragments.attachActivity(this);
mWindow = PolicyManager.makeNewWindow(this);//
......
mUiThread = Thread.currentThread();
mMainThread = aThread;
mInstrumentation = instr;
mToken = token;
mIdent = ident;
mApplication = application;
mIntent = intent;
mComponent = intent.getComponent();
mActivityInfo = info;
mTitle = title;
mParent = parent;
mEmbeddedID = id;
mLastNonConfigurationInstances = lastNonConfigurationInstances;
mWindow.setWindowManager(null, mToken, mComponent.flattenToString(),
(info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
if (mParent != null) {
mWindow.setContainer(mParent.getWindow());
}
mWindowManager = mWindow.getWindowManager();
mCurrentConfig = config;
}
public final class PolicyManager {
private static final String POLICY_IMPL_CLASS_NAME =
"com.android.internal.policy.impl.Policy";
private static final IPolicy sPolicy;
static {
try {
Class policyClass = Class.forName(POLICY_IMPL_CLASS_NAME);
sPolicy = (IPolicy)policyClass.newInstance();// Policy
} 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);
}
}
public static Window makeNewWindow(Context context) {
return sPolicy.makeNewWindow(context); //
}
.......
}
public class Policy implements IPolicy {
........
public PhoneWindow makeNewWindow(Context context) {
return new PhoneWindow(context);//
}
......
}
@Override
public void setContentView(int layoutResID) {
if (mContentParent == null){
installDecor();//1.
} else {
mContentParent.removeAllViews();
}
mLayoutInflater.inflate(layoutResID, mContentParent);//2.
final Callback cb = getCallback();
if (cb != null && !isDestroyed()) {
cb.onContentChanged();
}
}
private void installDecor() {
if (mDecor == null) {
mDecor = generateDecor();//1.
mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
mDecor.setIsRootNamespace(true);
}
if (mContentParent == null) {
mContentParent = generateLayout(mDecor);//2. ViewGroup
mDecor.makeOptionalFitsSystemWindows();
mTitleView = (TextView)findViewById(com.android.internal.R.id.title);
if (mTitleView != null) {
if ((getLocalFeatures() & (1 << FEATURE_NO_TITLE)) != 0) {
.......
} else {
mTitleView.setText(mTitle);// Activity title
}
} else {
mActionBar = (ActionBarView) findViewById(com.android.internal.R.id.action_bar);
if (mActionBar != null) {
.......mActionBar
}
}
}
}
protected DecorView generateDecor() {
return new DecorView(getContext(), -1);
}
private final class DecorView extends FrameLayout implements RootViewSurfaceTaker {
......
public DecorView(Context context, int featureId) {
super(context);
mFeatureId = featureId;
}
.......
protected ViewGroup generateLayout(DecorView decor) {
.......// window
// Inflate the window decor.
int layoutResource;
int features = getLocalFeatures();
// Activity feature
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;
}
removeFeature(FEATURE_ACTION_BAR);
} else if ((features & ((1 << FEATURE_PROGRESS) | (1 << FEATURE_INDETERMINATE_PROGRESS))) != 0
&& (features & (1 << FEATURE_ACTION_BAR)) == 0) {
//
layoutResource = com.android.internal.R.layout.screen_progress;
} else if ((features & (1 << FEATURE_CUSTOM_TITLE)) != 0) {
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;
}
removeFeature(FEATURE_ACTION_BAR);
} else if ((features & (1 << FEATURE_NO_TITLE)) == 0) {
// Titile
if (mIsFloating) {
TypedValue res = new TypedValue();
getContext().getTheme().resolveAttribute(
com.android.internal.R.attr.dialogTitleDecorLayout, res, true);
layoutResource = res.resourceId;
} else if ((features & (1 << FEATURE_ACTION_BAR)) != 0) {
if ((features & (1 << FEATURE_ACTION_BAR_OVERLAY)) != 0) {
layoutResource = com.android.internal.R.layout.screen_action_bar_overlay;
} else {
layoutResource = com.android.internal.R.layout.screen_action_bar;
}
} else {
layoutResource = com.android.internal.R.layout.screen_title;
}
} else if ((features & (1 << FEATURE_ACTION_MODE_OVERLAY)) != 0) {
layoutResource = com.android.internal.R.layout.screen_simple_overlay_action_mode;
} else {
layoutResource = com.android.internal.R.layout.screen_simple;//1.
}
mDecor.startChanging();
View in = mLayoutInflater.inflate(layoutResource, null);
decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));//2. View View
ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);//3. Activity ViewGroup
......
}
mDecor.finishChanging();
return contentParent;
}
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:fitsSystemWindows="true">
<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" />
<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>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:orientation="vertical">
<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" />
<FrameLayout
android:id="@android:id/content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:foregroundInsidePadding="false"
android:foregroundGravity="fill_horizontal|top"
android:foreground="?android:attr/windowContentOverlay" />
</LinearLayout>
View in = mLayoutInflater.inflate(layoutResource, null);
decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));//2. View View
ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);//3. Activity ViewGroup
@Override
public void setContentView(int layoutResID) {
if (mContentParent == null) {
installDecor();
} else {
mContentParent.removeAllViews();
}
mLayoutInflater.inflate(layoutResID, mContentParent);//
final Callback cb = getCallback();
if (cb != null && !isDestroyed()) {
cb.onContentChanged();
}
}
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
.......
Activity a = performLaunchActivity(r, customIntent);//1. Activity
if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
Bundle oldState = r.state;
handleResumeActivity(r.token, false, r.isForward);//2. Activity onResume
.......
} else {
.......
}
}
final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward) {
// If we are getting ready to gc after going to the background, well
// we are back active so skip it.
unscheduleGcIdler();
ActivityClientRecord r = performResumeActivity(token, clearHide);//1. Activity onResume
if (r != null) {
final Activity a = r.activity;
........
boolean willBeVisible = !a.mStartedActivity;
if (!willBeVisible) {
try {
willBeVisible = ActivityManagerNative.getDefault().willActivityBeVisible(a.getActivityToken());//2.Activity
} catch (RemoteException e) {
}
}
if (r.window == null && !a.mFinished && willBeVisible) {
r.window = r.activity.getWindow();
View decor = r.window.getDecorView();
decor.setVisibility(View.INVISIBLE);
ViewManager wm = a.getWindowManager();
WindowManager.LayoutParams l = r.window.getAttributes();
a.mDecor = decor;
l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
l.softInputMode |= forwardBit;
if (a.mVisibleFromClient) {
a.mWindowAdded = true;
wm.addView(decor, l);//3. WindowManager DecorView Window, Window,Activity 。
}
} else if (!willBeVisible) {
r.hideForNow = true;
}
cleanUpPendingRemoveWindows(r);
if (!r.activity.mFinished && willBeVisible&& r.activity.mDecor != null && !r.hideForNow) {
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();
wm.updateViewLayout(decor, l);//4. DecorView, Activity
}
}
r.activity.mVisibleFromServer = true;
mNumVisibleActivities++;
if (r.activity.mVisibleFromClient) {
r.activity.makeVisible();
}
}
.......
} else {
.......
}
}
Binder通信メカニズムの原理解析
Activity起動フローソース分析(応用中)
Activity起動フローソース分析(Launcher)