[Android-FrameWork]Android-PhoneWindow詳細分析
9560 ワード
Activityの層にはWindowとWindowManagementがあることはよく知られていますが、その対応は以下の通りです.
Activityが所有するWindowとWindowManagement
1.PhoneWindow 2.PhoneWindowManage
私たちが設定を始めたばかりの頃はこのように設定されていました
ついて行こう
まずこのgetWindowが何なのか見てみましょう
//このmWindowを見て
//ウィンドウマンをもう一度見て
PhoneWindowクラスにフォローし続けます
setContentViewに戻ります
Activityが所有するWindowとWindowManagement
1.PhoneWindow 2.PhoneWindowManage
私たちが設定を始めたばかりの頃はこのように設定されていました
setContentView(R.layout.activity_main);
ついて行こう
public void setContentView(@LayoutRes int layoutResID) {
getWindow().setContentView(layoutResID); // , getWindow
initWindowDecorActionBar();// DecorView ActionBar ,
//DecorView Activity
//PhoneWindow View
}
まずこのgetWindowが何なのか見てみましょう
public Window getWindow() {
return mWindow; // return mWindow
}
//このmWindowを見て
mWindow = new PhoneWindow(this, window, activityConfigCallback); // PhoneWindow
//ウィンドウマンをもう一度見て
mWindowManager = mWindow.getWindowManager();
// PhoneWindow WindowManager
PhoneWindowクラスにフォローし続けます
setContentViewに戻ります
/**
* XINHAO_HAN Activity View
* @param layoutResID
*/
@Override
public void setContentView(int layoutResID) {
// 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 ViewGroup
*/
if (mContentParent == null) {
/**
*
*/
installDecor();
} else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
/**
* View
*/
mContentParent.removeAllViews();
}
if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
getContext());
transitionTo(newScene);
} else {
mLayoutInflater.inflate(layoutResID, mContentParent);
}
mContentParent.requestApplyInsets();
final Callback cb = getCallback();
if (cb != null && !isDestroyed()) {
//
cb.onContentChanged();
}
mContentParentExplicitlySet = true;
}
引き続きinstallDecor()を見てみましょう. private void installDecor() {
mForceDecorInstall = false;
// DecorView DecorView
if (mDecor == null) {
//Decor ,
mDecor = generateDecor(-1);
//
mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
mDecor.setIsRootNamespace(true);
if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
}
} else {
mDecor.setWindow(this);
}
......
}
この方法generateDecor(-1)を見てみましょう.protected DecorView generateDecor(int featureId) {
// System process doesn't have application context and in that case we need to directly use
// the context we have. Otherwise we want the application context, so we don't cling to the
// activity.
Context context;
if (mUseDecorContext) {
Context applicationContext = getContext().getApplicationContext();
if (applicationContext == null) {
context = getContext();
} else {
context = new DecorContext(applicationContext, getContext().getResources());
if (mTheme != -1) {
context.setTheme(mTheme);
}
}
} else {
context = getContext();
}
return new DecorView(context, featureId, this, getAttributes());
}
これは直接newのDecorViewで、PhoneWindowに追加するViewに相当します. mEnterTransition = getTransition(mEnterTransition, null,
R.styleable.Window_windowEnterTransition);
mReturnTransition = getTransition(mReturnTransition, USE_DEFAULT_TRANSITION,
R.styleable.Window_windowReturnTransition);
mExitTransition = getTransition(mExitTransition, null,
R.styleable.Window_windowExitTransition);
mReenterTransition = getTransition(mReenterTransition, USE_DEFAULT_TRANSITION,
R.styleable.Window_windowReenterTransition);
mSharedElementEnterTransition = getTransition(mSharedElementEnterTransition, null,
R.styleable.Window_windowSharedElementEnterTransition);
mSharedElementReturnTransition = getTransition(mSharedElementReturnTransition,
USE_DEFAULT_TRANSITION,
R.styleable.Window_windowSharedElementReturnTransition);
mSharedElementExitTransition = getTransition(mSharedElementExitTransition, null,
R.styleable.Window_windowSharedElementExitTransition);
mSharedElementReenterTransition = getTransition(mSharedElementReenterTransition,
USE_DEFAULT_TRANSITION,
R.styleable.Window_windowSharedElementReenterTransition);
if (mAllowEnterTransitionOverlap == null) {
mAllowEnterTransitionOverlap = getWindowStyle().getBoolean(
R.styleable.Window_windowAllowEnterTransitionOverlap, true);
}
if (mAllowReturnTransitionOverlap == null) {
mAllowReturnTransitionOverlap = getWindowStyle().getBoolean(
R.styleable.Window_windowAllowReturnTransitionOverlap, true);
}
if (mBackgroundFadeDurationMillis < 0) {
mBackgroundFadeDurationMillis = getWindowStyle().getInteger(
R.styleable.Window_windowTransitionBackgroundFadeDuration,
DEFAULT_BACKGROUND_FADE_DURATION_MS);
}
if (mSharedElementsUseOverlay == null) {
mSharedElementsUseOverlay = getWindowStyle().getBoolean(
R.styleable.Window_windowSharedElementsUseOverlay, true);
}
//ユーザーが設定したテーマなど
そして感じなくなった?ないの??あり得ません.WindowManagerに追加されたものがあるはずです.そうしないと何も表示されません.
そしてActivity Threadで追加する方法を見つけました 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 (r.mPreserveWindow) {
a.mWindowAdded = true;
r.mPreserveWindow = false;
// Normally the ViewRoot sets up callbacks with the Activity
// in addView->ViewRootImpl#setView. If we are instead reusing
// the decor view we have to notify the view root that the
// callbacks may have changed.
ViewRootImpl impl = decor.getViewRootImpl();
if (impl != null) {
impl.notifyChildRebuilt();
}
}
if (a.mVisibleFromClient) {
if (!a.mWindowAdded) {
a.mWindowAdded = true;
// ------------------------------------------------------------------------------------
wm.addView(decor, l);
} else {
// The activity will get a callback for this {@link LayoutParams} change
// earlier. However, at that time the decor will not be set (this is set
// in this method), so no action will be taken. This call ensures the
// callback occurs with the decor set.
a.onWindowAttributesChanged(l);
}
}
ActivityではPhoneWindowのメンテナンスクラスに相当することがわかります。
すべてが初期化されたら(getDecorViewとPhoneWindow)Activity Threadで直接呼び出す
ナレッジポイント(まとめ)
1.ActivityのsetContentViewは、実際にはActivityに対応するWindow設定2である.Activity対応のWindowはPhoneWindow 3.ActivityのルートディレクトリはDecorViewで、Androidにはエンティティid androidがあります.R.id.content 4.Activity追加レイアウトはActivity Threadに追加され、PhoneWindowが初期化された後(DecorView)5.DecorViewのレイアウトはFramLayoutに統合されており、私たちが見ているように、ステータスバー、レイアウト、TitleBar、6を含む統一的なフォーマットがあります.ただし、ActivityのWindowManagerでViewを追加してgetApplicationContextのWindowManagerでViewを追加してみると、Activity-WindowManagerで追加したViewはActivityですべてのアプリに添付できないだけで、Activityが破棄された後にウィンドウが漏れている可能性があり、削除されていないが、潰れず、ヒントになる可能性があります.Activity-WindowManagerが追加したViewはActivityのライフサイクルによって変化しますが(バインドされています)、getApplicationContextが追加したWindowManagerのViewはシステム全体に漂っています
もう一つ、DialogはActivityでポップアップする必要はありません。これは参考にしてください。そして、これは根拠があります。皆さんの携帯電話の電力が15%未満の場合、あなたがそこにいてもDialogのヒントが15%未満であるかどうか、電源を接続してください。これは知識点です。
間違いがあったら大神さんを歓迎します。みんなで進歩します。
/**
* XINHAO_HAN Activity View
* @param layoutResID
*/
@Override
public void setContentView(int layoutResID) {
// 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 ViewGroup
*/
if (mContentParent == null) {
/**
*
*/
installDecor();
} else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
/**
* View
*/
mContentParent.removeAllViews();
}
if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
getContext());
transitionTo(newScene);
} else {
mLayoutInflater.inflate(layoutResID, mContentParent);
}
mContentParent.requestApplyInsets();
final Callback cb = getCallback();
if (cb != null && !isDestroyed()) {
//
cb.onContentChanged();
}
mContentParentExplicitlySet = true;
}
private void installDecor() {
mForceDecorInstall = false;
// DecorView DecorView
if (mDecor == null) {
//Decor ,
mDecor = generateDecor(-1);
//
mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
mDecor.setIsRootNamespace(true);
if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
}
} else {
mDecor.setWindow(this);
}
......
}
protected DecorView generateDecor(int featureId) {
// System process doesn't have application context and in that case we need to directly use
// the context we have. Otherwise we want the application context, so we don't cling to the
// activity.
Context context;
if (mUseDecorContext) {
Context applicationContext = getContext().getApplicationContext();
if (applicationContext == null) {
context = getContext();
} else {
context = new DecorContext(applicationContext, getContext().getResources());
if (mTheme != -1) {
context.setTheme(mTheme);
}
}
} else {
context = getContext();
}
return new DecorView(context, featureId, this, getAttributes());
}
mEnterTransition = getTransition(mEnterTransition, null,
R.styleable.Window_windowEnterTransition);
mReturnTransition = getTransition(mReturnTransition, USE_DEFAULT_TRANSITION,
R.styleable.Window_windowReturnTransition);
mExitTransition = getTransition(mExitTransition, null,
R.styleable.Window_windowExitTransition);
mReenterTransition = getTransition(mReenterTransition, USE_DEFAULT_TRANSITION,
R.styleable.Window_windowReenterTransition);
mSharedElementEnterTransition = getTransition(mSharedElementEnterTransition, null,
R.styleable.Window_windowSharedElementEnterTransition);
mSharedElementReturnTransition = getTransition(mSharedElementReturnTransition,
USE_DEFAULT_TRANSITION,
R.styleable.Window_windowSharedElementReturnTransition);
mSharedElementExitTransition = getTransition(mSharedElementExitTransition, null,
R.styleable.Window_windowSharedElementExitTransition);
mSharedElementReenterTransition = getTransition(mSharedElementReenterTransition,
USE_DEFAULT_TRANSITION,
R.styleable.Window_windowSharedElementReenterTransition);
if (mAllowEnterTransitionOverlap == null) {
mAllowEnterTransitionOverlap = getWindowStyle().getBoolean(
R.styleable.Window_windowAllowEnterTransitionOverlap, true);
}
if (mAllowReturnTransitionOverlap == null) {
mAllowReturnTransitionOverlap = getWindowStyle().getBoolean(
R.styleable.Window_windowAllowReturnTransitionOverlap, true);
}
if (mBackgroundFadeDurationMillis < 0) {
mBackgroundFadeDurationMillis = getWindowStyle().getInteger(
R.styleable.Window_windowTransitionBackgroundFadeDuration,
DEFAULT_BACKGROUND_FADE_DURATION_MS);
}
if (mSharedElementsUseOverlay == null) {
mSharedElementsUseOverlay = getWindowStyle().getBoolean(
R.styleable.Window_windowSharedElementsUseOverlay, true);
}
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 (r.mPreserveWindow) {
a.mWindowAdded = true;
r.mPreserveWindow = false;
// Normally the ViewRoot sets up callbacks with the Activity
// in addView->ViewRootImpl#setView. If we are instead reusing
// the decor view we have to notify the view root that the
// callbacks may have changed.
ViewRootImpl impl = decor.getViewRootImpl();
if (impl != null) {
impl.notifyChildRebuilt();
}
}
if (a.mVisibleFromClient) {
if (!a.mWindowAdded) {
a.mWindowAdded = true;
// ------------------------------------------------------------------------------------
wm.addView(decor, l);
} else {
// The activity will get a callback for this {@link LayoutParams} change
// earlier. However, at that time the decor will not be set (this is set
// in this method), so no action will be taken. This call ensures the
// callback occurs with the decor set.
a.onWindowAttributesChanged(l);
}
}
すべてが初期化されたら(getDecorViewとPhoneWindow)Activity Threadで直接呼び出す
ナレッジポイント(まとめ)
1.ActivityのsetContentViewは、実際にはActivityに対応するWindow設定2である.Activity対応のWindowはPhoneWindow 3.ActivityのルートディレクトリはDecorViewで、Androidにはエンティティid androidがあります.R.id.content 4.Activity追加レイアウトはActivity Threadに追加され、PhoneWindowが初期化された後(DecorView)5.DecorViewのレイアウトはFramLayoutに統合されており、私たちが見ているように、ステータスバー、レイアウト、TitleBar、6を含む統一的なフォーマットがあります.ただし、ActivityのWindowManagerでViewを追加してgetApplicationContextのWindowManagerでViewを追加してみると、Activity-WindowManagerで追加したViewはActivityですべてのアプリに添付できないだけで、Activityが破棄された後にウィンドウが漏れている可能性があり、削除されていないが、潰れず、ヒントになる可能性があります.Activity-WindowManagerが追加したViewはActivityのライフサイクルによって変化しますが(バインドされています)、getApplicationContextが追加したWindowManagerのViewはシステム全体に漂っています
もう一つ、DialogはActivityでポップアップする必要はありません。これは参考にしてください。そして、これは根拠があります。皆さんの携帯電話の電力が15%未満の場合、あなたがそこにいてもDialogのヒントが15%未満であるかどうか、電源を接続してください。これは知識点です。
間違いがあったら大神さんを歓迎します。みんなで進歩します。
1.ActivityのsetContentViewは、実際にはActivityに対応するWindow設定2である.Activity対応のWindowはPhoneWindow 3.ActivityのルートディレクトリはDecorViewで、Androidにはエンティティid androidがあります.R.id.content 4.Activity追加レイアウトはActivity Threadに追加され、PhoneWindowが初期化された後(DecorView)5.DecorViewのレイアウトはFramLayoutに統合されており、私たちが見ているように、ステータスバー、レイアウト、TitleBar、6を含む統一的なフォーマットがあります.ただし、ActivityのWindowManagerでViewを追加してgetApplicationContextのWindowManagerでViewを追加してみると、Activity-WindowManagerで追加したViewはActivityですべてのアプリに添付できないだけで、Activityが破棄された後にウィンドウが漏れている可能性があり、削除されていないが、潰れず、ヒントになる可能性があります.Activity-WindowManagerが追加したViewはActivityのライフサイクルによって変化しますが(バインドされています)、getApplicationContextが追加したWindowManagerのViewはシステム全体に漂っています