Windowに関する知識
6564 ワード
Activityの階層はActivity->PhoneWindow->decorView->appbarとcontentViewに分けられ、phoneWindowはwindowの唯一の実装であり、phoneWindowがactivityのattachメソッドでActivityを初期化するattachはAMSがActivity ThreadのhandleMessageでlaunchActivityメソッド呼び出しを実行し、attachを実行するとActivityのonCreateメソッドを実行する
ユーザーがsetContentViewを呼び出すと、継承された関係によって2つに分けられます.1.ActivityまたはFragmentActivityを継承してwindowを直接呼び出すsetContentViewメソッド
PhoneWindowでの疑似コードは
最初のステップは、mContentParentが空の場合、つまりdeCorViewが初期化されていない場合、installDecorを実行することです.
ここでgenerateDecorはnewのDecorViewです
generateLayoutメソッドは主にdecorViewのプロパティを初期化します.例えば、タイトルの設定、アイコンのページスタイルの設定などです.私たちはコードで全画面を設定します.なぜsetCotentViewの前にこの理由がありますか.
2.継承AppCompatActivityは、コンパイルされたシステムバージョンに従ってオブジェクトmDelegateオブジェクト@Override public void setContentView(@LayoutResint layoutResID){getDelegate().setContentView(layoutResID);setContentViewは最終的にAppCompatDelegateImplV 7のsetContentViewメソッドを呼び出す
EnsureSubDecorメソッドは、最終的に設定に従って「subDecor」をロードするレイアウトを呼び出し、activityとは異なりdecorViewを使用しません.
WindowaManagerはactivityのattachで初期化され、それ自体がインタフェースクラスであり、インタフェースViewManagerを継承する.この3つの方法は、WindowManagerがactivity制御Viewに提供する
WindowaManager実装クラスはWindowManagerImplで、中はWindowManagerGlobalを取得して、具体的な方法の実装です
WindowManagerには3つの配列が格納されています
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
//....
if (activity != null) {
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config,
r.referrer, r.voiceInteractor);
//....
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
}
ユーザーがsetContentViewを呼び出すと、継承された関係によって2つに分けられます.1.ActivityまたはFragmentActivityを継承してwindowを直接呼び出すsetContentViewメソッド
public void setContentView(@LayoutRes int layoutResID) {
getWindow().setContentView(layoutResID);
initWindowDecorActionBar();
}
PhoneWindowでの疑似コードは
@Override
public void setContentView(int layoutResID) {
if (mContentParent == null) {
installDecor();
}
// app
mLayoutInflater.inflate(layoutResID, mContentParent);
}
最初のステップは、mContentParentが空の場合、つまりdeCorViewが初期化されていない場合、installDecorを実行することです.
private void installDecor() {
if (mDecor == null) {
mDecor = generateDecor();
}
if (mContentParent == null) {
mContentParent = generateLayout(mDecor);
if (decorContentParent != null) {
mDecorContentParent = decorContentParent;
} else {
//...
}
}
ここでgenerateDecorはnewのDecorViewです
protected DecorView generateDecor() {
return new DecorView(getContext(), -1);
}
//
private final class DecorView extends FrameLayout implements RootViewSurfaceTaker
generateLayoutメソッドは主にdecorViewのプロパティを初期化します.例えば、タイトルの設定、アイコンのページスタイルの設定などです.私たちはコードで全画面を設定します.なぜsetCotentViewの前にこの理由がありますか.
if (a.getBoolean(R.styleable.Window_windowNoTitle, false)) {
requestFeature(FEATURE_NO_TITLE);
} else if (a.getBoolean(R.styleable.Window_windowActionBar, false)) {
// Don't allow an action bar if there is no title.
requestFeature(FEATURE_ACTION_BAR);
}
2.継承AppCompatActivityは、コンパイルされたシステムバージョンに従ってオブジェクトmDelegateオブジェクト@Override public void setContentView(@LayoutResint layoutResID){getDelegate().setContentView(layoutResID);setContentViewは最終的にAppCompatDelegateImplV 7のsetContentViewメソッドを呼び出す
@Override
public void setContentView(int resId) {
ensureSubDecor();
ViewGroup contentParent = (ViewGroup) mSubDecor.findViewById(android.R.id.content);
contentParent.removeAllViews();
LayoutInflater.from(mContext).inflate(resId, contentParent);
mOriginalWindowCallback.onContentChanged();
}
EnsureSubDecorメソッドは、最終的に設定に従って「subDecor」をロードするレイアウトを呼び出し、activityとは異なりdecorViewを使用しません.
private ViewGroup createSubDecor() {
TypedArray a = mContext.obtainStyledAttributes(R.styleable.Theme);
//
if (a.getBoolean(R.styleable.Theme_windowNoTitle, false)) {
requestWindowFeature(Window.FEATURE_NO_TITLE);
} else if (a.getBoolean(R.styleable.Theme_windowActionBar, false)) {
// Don't allow an action bar if there is no title.
requestWindowFeature(FEATURE_SUPPORT_ACTION_BAR);
}
final LayoutInflater inflater = LayoutInflater.from(mContext);
ViewGroup subDecor = null;
if (!mWindowNoTitle) {
if (mIsFloating) {
// If we're floating, inflate the dialog title decor
subDecor = (ViewGroup) inflater.inflate(
R.layout.abc_dialog_title_material, null);
// Floating windows can never have an action bar, reset the flags
mHasActionBar = mOverlayActionBar = false;
} else if (mHasActionBar) {
// Now inflate the view using the themed context and set it as the content view
subDecor = (ViewGroup) LayoutInflater.from(themedContext)
.inflate(R.layout.abc_screen_toolbar, null);
mDecorContentParent = (DecorContentParent) subDecor
.findViewById(R.id.decor_content_parent);
}
} else {
if (mOverlayActionMode) {
subDecor = (ViewGroup) inflater.inflate(
R.layout.abc_screen_simple_overlay_action_mode, null);
} else {
subDecor = (ViewGroup) inflater.inflate(R.layout.abc_screen_simple, null);
}
// Now set the Window's content view with the decor
mWindow.setContentView(subDecor);
return subDecor;
}
WindowaManagerはactivityのattachで初期化され、それ自体がインタフェースクラスであり、インタフェースViewManagerを継承する.この3つの方法は、WindowManagerがactivity制御Viewに提供する
public interface ViewManager
{
public void addView(View view, ViewGroup.LayoutParams params);
public void updateViewLayout(View view, ViewGroup.LayoutParams params);
public void removeView(View view);
}
WindowaManager実装クラスはWindowManagerImplで、中はWindowManagerGlobalを取得して、具体的な方法の実装です
public final class WindowManagerImpl implements WindowManager {
private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
@Override
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
applyDefaultToken(params);
mGlobal.addView(view, params, mDisplay, mParentWindow);
}
@Override
public void updateViewLayout(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
applyDefaultToken(params);
mGlobal.updateViewLayout(view, params);
}
@Override
public void removeView(View view) {
mGlobal.removeView(view, false);
}
}
WindowManagerには3つの配列が格納されています
// View
private final ArrayList mViews = new ArrayList();
private final ArrayList mRoots = new ArrayList();
// view
private final ArrayList mParams =
new ArrayList();