Activity的onAttachedToWindow和onDetachedFromWindow呼叫時機原始碼解析
阿新 • • 發佈:2019-01-29
先上測試程式碼:
MyView.java
[java] view plain copy print?- import android.content.Context;
- import android.util.AttributeSet;
- import android.util.Log;
- import android.widget.TextView;
- publicclass MyView extends TextView {
- public MyView(Context context) {
- super(context);
- }
- public MyView(Context context, AttributeSet attrs) {
- super(context, attrs);
- Log.e(”test”,“view constructor”);
- }
- @Override
- protectedvoid onAttachedToWindow() {
- super.onAttachedToWindow();
- Log.e(”test”, “onAttachedToWindow”);
- }
- @Override
- protectedvoid onDetachedFromWindow() {
- super.onDetachedFromWindow();
- Log.e(”test”, “onDetachedFromWindow”);
- }
- }
import android.content.Context; import android.util.AttributeSet; import android.util.Log; import android.widget.TextView; public class MyView extends TextView { public MyView(Context context) { super(context); } public MyView(Context context, AttributeSet attrs) { super(context, attrs); Log.e("test","view constructor"); } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); Log.e("test", "onAttachedToWindow"); } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); Log.e("test", "onDetachedFromWindow"); } }
MainActivity.java
[java] view plain copy print?- import android.support.v7.app.AppCompatActivity;
- import android.os.Bundle;
- import android.util.Log;
- publicclass MainActivity extends AppCompatActivity {
- @Override
- protectedvoid onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- Log.e(”test”, “before setContextView”);
- setContentView(R.layout.activity_main);
- Log.e(”test”, “after setContextView”);
- }
- @Override
- protectedvoid onResume() {
- super.onResume();
- Log.e(”test”, “onResume”);
- }
- @Override
- protectedvoid onDestroy() {
- super.onDestroy();
- Log.e(”test”, “onDestroy”);
- }
- }
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.e("test", "before setContextView");
setContentView(R.layout.activity_main);
Log.e("test", "after setContextView");
}
@Override
protected void onResume() {
super.onResume();
Log.e("test", "onResume");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.e("test", "onDestroy");
}
}
執行後輸出的Log如下:
點選返回鍵退出後,輸出的Log如下:
根據Log的onAttachedToWindow和onDetachedFromWindow的輸出情況一目瞭然。
下面通過原始碼分析下,他兩的呼叫時機到底在哪。
首先看下onAttachedToWindow的呼叫時機,在Android原始碼中onResume呼叫前會先呼叫了ActivityThread中的handleResumeActivity,下面是相應的程式碼:
ActivityThread.java
[java] view plain copy print?- finalvoid handleResumeActivity(IBinder token,
- boolean clearHide, boolean isForward, boolean reallyResume) {
- // If we are getting ready to gc after going to the background, well
- // we are back active so skip it.
- unscheduleGcIdler();
- mSomeActivitiesChanged = true;
- // TODO Push resumeArgs into the activity for consideration
- ActivityClientRecord r = performResumeActivity(token, clearHide);
- if (r != null) {
- final Activity a = r.activity;
- if (localLOGV) Slog.v(
- TAG, ”Resume ” + r + “ started activity: ” +
- a.mStartedActivity + ”, hideForNow: ” + r.hideForNow
- + ”, finished: ” + a.mFinished);
- finalint forwardBit = isForward ?
- WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION : 0;
- // If the window hasn’t yet been added to the window manager,
- // and this guy didn’t finish itself or start another activity,
- // then go ahead and add the window.
- boolean willBeVisible = !a.mStartedActivity;
- if (!willBeVisible) {
- try {
- willBeVisible = ActivityManagerNative.getDefault().willActivityBeVisible(
- a.getActivityToken());
- } 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);//這裡呼叫了ViewManager中的addView方法。
- }
- // If the window has already been added, but during resume
- // we started another activity, then don’t yet make the
- // window visible.
- } elseif (!willBeVisible) {
- if (localLOGV) Slog.v(
- TAG, ”Launch ” + r + “ mStartedActivity set”);
- r.hideForNow = true;
- }
- // Get rid of anything left hanging around.
- cleanUpPendingRemoveWindows(r);
- // The window is now visible if it has been added, we are not
- // simply finishing, and we are not starting another activity.
- if (!r.activity.mFinished && willBeVisible
- && r.activity.mDecor != null && !r.hideForNow) {
- if (r.newConfig != null) {
- r.tmpConfig.setTo(r.newConfig);
- if (r.overrideConfig != null) {
- r.tmpConfig.updateFrom(r.overrideConfig);
- }
- if (DEBUG_CONFIGURATION) Slog.v(TAG, “Resuming activity ”
- + r.activityInfo.name + ” with newConfig ” + r.tmpConfig);
- performConfigurationChanged(r.activity, r.tmpConfig);
- freeTextLayoutCachesIfNeeded(r.activity.mCurrentConfig.diff(r.tmpConfig));
- r.newConfig = null;
- }
- if (localLOGV) Slog.v(TAG, “Resuming ” + r + “ with isForward=”
- + isForward);
- 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);
- }
- }
- r.activity.mVisibleFromServer = true;
- mNumVisibleActivities++;
- if (r.activity.mVisibleFromClient) {
- r.activity.makeVisible();
- }
- }
- ….
- }
final void handleResumeActivity(IBinder token,
boolean clearHide, boolean isForward, boolean reallyResume) {
// If we are getting ready to gc after going to the background, well
// we are back active so skip it.
unscheduleGcIdler();
mSomeActivitiesChanged = true;
// TODO Push resumeArgs into the activity for consideration
ActivityClientRecord r = performResumeActivity(token, clearHide);
if (r != null) {
final Activity a = r.activity;
if (localLOGV) Slog.v(
TAG, "Resume " + r + " started activity: " +
a.mStartedActivity + ", hideForNow: " + r.hideForNow
+ ", finished: " + a.mFinished);
final int forwardBit = isForward ?
WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION : 0;
// If the window hasn't yet been added to the window manager,
// and this guy didn't finish itself or start another activity,
// then go ahead and add the window.
boolean willBeVisible = !a.mStartedActivity;
if (!willBeVisible) {
try {
willBeVisible = ActivityManagerNative.getDefault().willActivityBeVisible(
a.getActivityToken());
} 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);//這裡呼叫了ViewManager中的addView方法。
}
// If the window has already been added, but during resume
// we started another activity, then don't yet make the
// window visible.
} else if (!willBeVisible) {
if (localLOGV) Slog.v(
TAG, "Launch " + r + " mStartedActivity set");
r.hideForNow = true;
}
// Get rid of anything left hanging around.
cleanUpPendingRemoveWindows(r);
// The window is now visible if it has been added, we are not
// simply finishing, and we are not starting another activity.
if (!r.activity.mFinished && willBeVisible
&& r.activity.mDecor != null && !r.hideForNow) {
if (r.newConfig != null) {
r.tmpConfig.setTo(r.newConfig);
if (r.overrideConfig != null) {
r.tmpConfig.updateFrom(r.overrideConfig);
}
if (DEBUG_CONFIGURATION) Slog.v(TAG, "Resuming activity "
+ r.activityInfo.name + " with newConfig " + r.tmpConfig);
performConfigurationChanged(r.activity, r.tmpConfig);
freeTextLayoutCachesIfNeeded(r.activity.mCurrentConfig.diff(r.tmpConfig));
r.newConfig = null;
}
if (localLOGV) Slog.v(TAG, "Resuming " + r + " with isForward="
+ isForward);
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);
}
}
r.activity.mVisibleFromServer = true;
mNumVisibleActivities++;
if (r.activity.mVisibleFromClient) {
r.activity.makeVisible();
}
}
....
}
看程式碼中的wm.addView(devor,l);通過該方法將View新增到Window當中(在當前Window也就是Activity,不過Window也可以是Dialog或Toast),而wm是ViewManager型別的,檢視對應程式碼是:[java] view plain copy print?- package android.view;
- /** Interface to let you add and remove child views to an Activity. To get an instance
- * of this class, call {@link android.content.Context#getSystemService(java.lang.String) Context.getSystemService()}.
- */
- publicinterface ViewManager
- {
- /**
- * Assign the passed LayoutParams to the passed View and add the view to the window.
- * <p>Throws {@link android.view.WindowManager.BadTokenException} for certain programming
- * errors, such as adding a second view to a window without removing the first view.
- * <p>Throws {@link android.view.WindowManager.InvalidDisplayException} if the window is on a
- * secondary {@link Display} and the specified display can’t be found
- * (see {@link android.app.Presentation}).
- * @param view The view to be added to this window.
- * @param params The LayoutParams to assign to view.
- */
- publicvoid addView(View view, ViewGroup.LayoutParams params);
- publicvoid updateViewLayout(View view, ViewGroup.LayoutParams params);
- publicvoid removeView(View view);
- }
package android.view;
/** Interface to let you add and remove child views to an Activity. To get an instance
* of this class, call {@link android.content.Context#getSystemService(java.lang.String) Context.getSystemService()}.
*/
public interface ViewManager
{
/**
* Assign the passed LayoutParams to the passed View and add the view to the window.
* <p>Throws {@link android.view.WindowManager.BadTokenException} for certain programming
* errors, such as adding a second view to a window without removing the first view.
* <p>Throws {@link android.view.WindowManager.InvalidDisplayException} if the window is on a
* secondary {@link Display} and the specified display can't be found
* (see {@link android.app.Presentation}).
* @param view The view to be added to this window.
* @param params The LayoutParams to assign to view.
*/
public void addView(View view, ViewGroup.LayoutParams params);
public void updateViewLayout(View view, ViewGroup.LayoutParams params);
public void removeView(View view);
}
該類是一個介面,在他下面還有一個WindowManager繼承於ViewManager,而真正的實現程式碼在WindowManagerImpl類中,程式碼如下:WindowManagerImpl.java
[java] view plain copy print?- /*
- * @see WindowManager
- * @see WindowManagerGlobal
- * @hide
- */
- ublic finalclass WindowManagerImpl implements WindowManager {
- privatefinal WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
- privatefinal Display mDisplay;
- privatefinal Window mParentWindow;
- private IBinder mDefaultToken;
- public WindowManagerImpl(Display display) {
- this(display, null);
- }
- private WindowManagerImpl(Display display, Window parentWindow) {
- mDisplay = display;
- mParentWindow = parentWindow;
- }
- public WindowManagerImpl createLocalWindowManager(Window parentWindow) {
- returnnew WindowManagerImpl(mDisplay, parentWindow);
- }
- public WindowManagerImpl createPresentationWindowManager(Display display) {
- returnnew WindowManagerImpl(display, mParentWindow);
- }
- /**
- * Sets the window token to assign when none is specified by the client or
- * available from the parent window.
- *
- * @param token The default token to assign.
- */
- publicvoid setDefaultToken(IBinder token) {
- mDefaultToken = token;
- }
- @Override
- publicvoid addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
- applyDefaultToken(params);
- mGlobal.addView(view, params, mDisplay, mParentWindow);
- }
- @Override
- publicvoid updateViewLayout(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
- applyDefaultToken(params);
- mGlobal.updateViewLayout(view, params);
- }
- privatevoid applyDefaultToken(@NonNull ViewGroup.LayoutParams params) {
- // Only use the default token if we don’t have a parent window.
- if (mDefaultToken != null && mParentWindow == null) {
- if (!(params instanceof WindowManager.LayoutParams)) {
- thrownew IllegalArgumentException(“Params must be WindowManager.LayoutParams”);
- }
- // Only use the default token if we don’t already have a token.
- final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
- if (wparams.token == null) {
- wparams.token = mDefaultToken;
- }
- }
- }
- @Override
- publicvoid removeView(View view) {
- mGlobal.removeView(view, false);
- }
- @Override
- publicvoid removeViewImmediate(View view) {
- mGlobal.removeView(view, true);
- }
- @Override
- public Display getDefaultDisplay() {
- return mDisplay;
- }
/*
* @see WindowManager
* @see WindowManagerGlobal
* @hide
*/
public final class WindowManagerImpl implements WindowManager {
private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
private final Display mDisplay;
private final Window mParentWindow;
private IBinder mDefaultToken;
public WindowManagerImpl(Display display) {
this(display, null);
}
private WindowManagerImpl(Display display, Window parentWindow) {
mDisplay = display;
mParentWindow = parentWindow;
}
public WindowManagerImpl createLocalWindowManager(Window parentWindow) {
return new WindowManagerImpl(mDisplay, parentWindow);
}
public WindowManagerImpl createPresentationWindowManager(Display display) {
return new WindowManagerImpl(display, mParentWindow);
}
/**
* Sets the window token to assign when none is specified by the client or
* available from the parent window.
*
* @param token The default token to assign.
*/
public void setDefaultToken(IBinder token) {
mDefaultToken = token;
}
@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);
}
private void applyDefaultToken(@NonNull ViewGroup.LayoutParams params) {
// Only use the default token if we don't have a parent window.
if (mDefaultToken != null && mParentWindow == null) {
if (!(params instanceof WindowManager.LayoutParams)) {
throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");
}
// Only use the default token if we don't already have a token.
final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
if (wparams.token == null) {
wparams.token = mDefaultToken;
}
}
}
@Override
public void removeView(View view) {
mGlobal.removeView(view, false);
}
@Override
public void removeViewImmediate(View view) {
mGlobal.removeView(view, true);
}
@Override
public Display getDefaultDisplay() {
return mDisplay;
}
}
[java] view plain copy print?從中可以看到addView又呼叫了 WindowManagerGlobal.java類中的addView,下面看看WindowManagerGlobal.java類的原始碼:
WindowManagerGlobal.java
[java] view plain copy print?- publicvoid addView(View view, ViewGroup.LayoutParams params,
- Display display, Window parentWindow) {
- if (view == null) {
- thrownew IllegalArgumentException(“view must not be null”);
- }
- if (display == null) {
- thrownew IllegalArgumentException(“display must not be null”);
- }
- if (!(params instanceof WindowManager.LayoutParams)) {
- thrownew IllegalArgumentException(“Params must be WindowManager.LayoutParams”);
- }
- final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
- if (parentWindow != null) {
- parentWindow.adjustLayoutParamsForSubWindow(wparams);
- } else {
- // If there’s no parent, then hardware acceleration for this view is
- // set from the application’s hardware acceleration setting.
- final Context context = view.getContext();
- if (context != null
- && (context.getApplicationInfo().flags
- & ApplicationInfo.FLAG_HARDWARE_ACCELERATED) != 0) {
- wparams.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
- }
- }
- ViewRootImpl root;
- View panelParentView = null;
- synchronized (mLock) {
- // Start watching for system property changes.
- if (mSystemPropertyUpdater == null) {
- mSystemPropertyUpdater = new Runnable() {
- @Overridepublicvoid run() {
- synchronized (mLock) {
- for (int i = mRoots.size() - 1; i >= 0; –i) {
- mRoots.get(i).loadSystemProperties();
- }
- }
- }
- };
- SystemProperties.addChangeCallback(mSystemPropertyUpdater);
- }
- int index = findViewLocked(view, false);
- if (index >= 0) {
- if (mDyingViews.contains(view)) {
- // Don’t wait for MSG_DIE to make it’s way through root’s queue.
- mRoots.get(index).doDie();
- } else {
- thrownew IllegalStateException(“View ” + view
- + ” has already been added to the window manager.”);
- }
- // The previous removeView() had not completed executing. Now it has.
- }
- // If this is a panel window, then find the window it is being
- // attached to for future reference.
- if (wparams.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW &&
- wparams.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
- finalint count = mViews.size();
- for (int i = 0; i < count; i++) {
- if (mRoots.get(i).mWindow.asBinder() == wparams.token) {
- panelParentView = mViews.get(i);
- }
- }
- }
- root = new ViewRootImpl(view.getContext(), display);
- view.setLayoutParams(wparams);
- mViews.add(view);
- mRoots.add(root);
- mParams.add(wparams);
- }
- // do this last because it fires off messages to start doing things
- try {
- root.setView(view, wparams, panelParentView);//這裡呼叫ViewRootImpl類中的setView方法,在該方法中觸發了<span style=”color:rgb(101,123,131);font-family:Menlo, Monaco, Consolas, ‘Courier New’, monospace;line-height:20.4px;white-space:pre-wrap;background-color:rgb(246,246,246);”>ViewRootImpl.performTraversals()</span>
- } catch (RuntimeException e) {
- // BadTokenException or InvalidDisplayException, clean up.
- synchronized (mLock) {
- finalint index = findViewLocked(view, false);
- if (index >= 0) {
- removeViewLocked(index, true);
- }
- }
- throw e;
- }
- }
public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow) {
if (view == null) {
throw new IllegalArgumentException("view must not be null");
}
if (display == null) {
throw new IllegalArgumentException("display must not be null");
}
if (!(params instanceof WindowManager.LayoutParams)) {
throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");
}
final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
if (parentWindow != null) {
parentWindow.adjustLayoutParamsForSubWindow(wparams);
} else {
// If there's no parent, then hardware acceleration for this view is
// set from the application's hardware acceleration setting.
final Context context = view.getContext();
if (context != null
&& (context.getApplicationInfo().flags
& ApplicationInfo.FLAG_HARDWARE_ACCELERATED) != 0) {
wparams.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
}
}
ViewRootImpl root;
View panelParentView = null;
synchronized (mLock) {
// Start watching for system property changes.
if (mSystemPropertyUpdater == null) {
mSystemPropertyUpdater = new Runnable() {
@Override public void run() {
synchronized (mLock) {
for (int i = mRoots.size() - 1; i >= 0; --i) {
mRoots.get(i).loadSystemProperties();
}
}
}
};
SystemProperties.addChangeCallback(mSystemPropertyUpdater);
}
int index = findViewLocked(view, false);
if (index >= 0) {
if (mDyingViews.contains(view)) {
// Don't wait for MSG_DIE to make it's way through root's queue.
mRoots.get(index).doDie();
} else {
throw new IllegalStateException("View " + view
+ " has already been added to the window manager.");
}
// The previous removeView() had not completed executing. Now it has.
}
// If this is a panel window, then find the window it is being
// attached to for future reference.
if (wparams.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW &&
wparams.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
final int count = mViews.size();
for (int i = 0; i < count; i++) {
if (mRoots.get(i).mWindow.asBinder() == wparams.token) {
panelParentView = mViews.get(i);
}
}
}
root = new ViewRootImpl(view.getContext(), display);
view.setLayoutParams(wparams);
mViews.add(view);
mRoots.add(root);
mParams.add(wparams);
}
// do this last because it fires off messages to start doing things
try {
root.setView(view, wparams, panelParentView);//這裡呼叫ViewRootImpl類中的setView方法,在該方法中觸發了ViewRootImpl.performTraversals()
} catch (RuntimeException e) {
// BadTokenException or InvalidDisplayException, clean up.
synchronized (mLock) {
final int index = findViewLocked(view, false);
if (index >= 0) {
removeViewLocked(index, true);
}
}
throw e;
}
}
在該方法中的root.setView(view,wparams,panelParentView)方法,呼叫的是ViewRootImpl類中的setView方法,正是該setView方法觸發了ViewRootImpl.performTraversals()方法,也就是View繪製的起點,之後會進行measure,layout,draw三個步驟從而完成一個View的顯示工作。
ViewRootImpl.java
[java] view plain copy print?- /**
- * We have one child
- */
- publicvoid setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
- synchronized (this) {
- if (mView == null) {
- mView = view;
- mAttachInfo.mDisplayState = mDisplay.getState();
- mDisplayManager.registerDisplayListener(mDisplayListener, mHandler);
- …
- mSoftInputMode = attrs.softInputMode;
- mWindowAttributesChanged = true;
- mWindowAttributesChangesFlag = WindowManager.LayoutParams.EVERYTHING_CHANGED;
- mAttachInfo.mRootView = view;
- mAttachInfo.mScalingRequired = mTranslator != null;
- mAttachInfo.mApplicationScale =
- mTranslator == null ? 1.0f : mTranslator.applicationScale;
- if (panelParentView != null) {
- mAttachInfo.mPanelParentWindowToken
- = panelParentView.getApplicationWindowToken();
- }
- mAdded = true;
- int res; /* = WindowManagerImpl.ADD_OKAY; */
- // Schedule the first layout -before- adding to the window
- // manager, to make sure we do the relayout before receiving
- // any other events from the system.
- requestLayout();//這裡開始請求view的繪製
- if ((mWindowAttributes.inputFeatures
- & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
- mInputChannel = new InputChannel();
- }
- try {
- mOrigWindowType = mWindowAttributes.type;
- mAttachInfo.mRecomputeGlobalAttributes = true;
- collectViewAttributes();
- res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
- getHostVisibility(), mDisplay.getDisplayId(),
- mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
- mAttachInfo.mOutsets, mInputChannel);
- } catch (RemoteException e) {
- mAdded = false;
- mView = null;
- mAttachInfo.mRootView = null;
- mInputChannel = null;
- mFallbackEventHandler.setView(null);
- unscheduleTraversals();
- setAccessibilityFocus(null, null);