Activity窗口視圖創(chuàng)建顯示過(guò)程源碼分析
- Android 6.0 & API Level 23
- Github: Nvsleep
- 郵箱: lizhenqiao@126.com
簡(jiǎn)述
- 一般情況, 我們?cè)贏ctivity繼承類(lèi)重寫(xiě)onCreate()方法中會(huì)調(diào)用Activity.setContentView()方法傳入需要顯示的視圖資源id或是View.
- 本文主要分析了從調(diào)用setContentView()起到Activity的視圖窗口測(cè)量,布局,繪制的中間過(guò)程.
S1: ActivityThread.handleLaunchActivity()
- 由上文[Activity啟動(dòng)過(guò)程源碼分析]可知,acitivity的實(shí)際生成和啟動(dòng)的入口是APP當(dāng)前進(jìn)程的ActivityThread的內(nèi)部類(lèi)ApplicationThread.scheduleLaunchActivity()方法;
- 該方法通過(guò)Handler發(fā)送消息到當(dāng)前進(jìn)程主線程并調(diào)用ActivityThread.handleLaunchActivity()方法;
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
....
Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
Bundle oldState = r.state;
handleResumeActivity(r.token, false, r.isForward,!r.activity.mFinished && !r.startsNotResumed);
....
}
....
}
S2: ActivityThread.performLaunchActivity()
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
// 先是獲取當(dāng)前要啟動(dòng)的acitivity的一些信息,主要是packageInfo和component
ActivityInfo aInfo = r.activityInfo;
if (r.packageInfo == null) {
r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
Context.CONTEXT_INCLUDE_CODE);
}
ComponentName component = r.intent.getComponent();
if (component == null) {
component = r.intent.resolveActivity(
mInitialApplication.getPackageManager());
r.intent.setComponent(component);
}
if (r.activityInfo.targetActivity != null) {
component = new ComponentName(r.activityInfo.packageName,
r.activityInfo.targetActivity);
}
Activity activity = null;
try {
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
// 通過(guò)反射生成acitivity對(duì)象先
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
r.intent.prepareToEnterProcess();
if (r.state != null) {
r.state.setClassLoader(cl);
}
} catch (Exception e) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to instantiate activity " + component
+ ": " + e.toString(), e);
}
}
try {
// 生成當(dāng)前APP的Application對(duì)象,并調(diào)用其onCreate()
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
if (activity != null) {
// 為了當(dāng)前acitivity生成一個(gè)ContextImpl對(duì)象
Context appContext = createBaseContextForActivity(r, activity);
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
Configuration config = new Configuration(mCompatConfiguration);
// 為當(dāng)前acitivity初始化設(shè)置一些必要的參數(shù)
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 (customIntent != null) {
activity.mIntent = customIntent;
}
r.lastNonConfigurationInstances = null;
activity.mStartedActivity = false;
int theme = r.activityInfo.getThemeResource();
if (theme != 0) {
activity.setTheme(theme);
}
activity.mCalled = false;
// acitivity生命周期的onCreate()在此調(diào)用
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
// 如果沒(méi)有調(diào)用父類(lèi)的onCreate()方法則,activity.mCalled == false,拋出異常!
if (!activity.mCalled) {
throw new SuperNotCalledException(
"Activity " + r.intent.getComponent().toShortString() +
" did not call through to super.onCreate()");
}
r.activity = activity;
r.stopped = true;
if (!r.activity.mFinished) {
activity.performStart();
r.stopped = false;
}
if (!r.activity.mFinished) {
if (r.isPersistable()) {
if (r.state != null || r.persistentState != null) {
mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,
r.persistentState);
}
} else if (r.state != null) {
mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
}
}
if (!r.activity.mFinished) {
activity.mCalled = false;
// 看情況是否需要調(diào)用onRestoreInstanceState()方法做一些恢復(fù)數(shù)據(jù)操作
if (r.isPersistable()) {
mInstrumentation.callActivityOnPostCreate(activity, r.state,
r.persistentState);
} else {
mInstrumentation.callActivityOnPostCreate(activity, r.state);
}
if (!activity.mCalled) {
throw new SuperNotCalledException(
"Activity " + r.intent.getComponent().toShortString() +
" did not call through to super.onPostCreate()");
}
}
}
// 還沒(méi)有顯示出來(lái),所以這里先設(shè)置為true
r.paused = true;
// 保存當(dāng)前acitivity信息到該進(jìn)程的ActivityThread對(duì)象中,下面需要取出來(lái)用到
mActivities.put(r.token, r);
} catch ....
}
在通過(guò)反射生成acitivity對(duì)象后,即調(diào)用了Activity.attach()方法初始化設(shè)置,這個(gè)是其生命周期方法onCreate()之前調(diào)用的;
S3: 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, String referrer, IVoiceInteractor voiceInteractor) {
// 賦值上一步為當(dāng)前acitivity生成的Context對(duì)象,實(shí)際是ContextImpl對(duì)象
attachBaseContext(context);
// acitivity的FragmentController mFragments成員變量初始化設(shè)置
mFragments.attachHost(null /*parent*/);
// 為當(dāng)前acitivity設(shè)置Window對(duì)象
mWindow = new PhoneWindow(this);
// 把當(dāng)前acitivity對(duì)象設(shè)置到Window作為通知回調(diào)
mWindow.setCallback(this);
mWindow.setOnWindowDismissedCallback(this);
// 這個(gè)在XML中直接寫(xiě)Framgent時(shí)候返回調(diào)用acitivity中的生成view的方法
mWindow.getLayoutInflater().setPrivateFactory(this);
// 設(shè)置輸入法模式
if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
mWindow.setSoftInputMode(info.softInputMode);
}
if (info.uiOptions != 0) {
mWindow.setUiOptions(info.uiOptions);
}
// 這個(gè)當(dāng)然是主線程啦
mUiThread = Thread.currentThread();
// 保存該應(yīng)用程序進(jìn)程的AcitivityThread進(jìn)程入口對(duì)象信息
mMainThread = aThread;
mInstrumentation = instr;
// 描述當(dāng)前acitivity的一個(gè)特征對(duì)象,實(shí)際最初是ActivityStackSupervisor.startActivityLocked()
// 中生成ActivityRecord對(duì)象時(shí)候生成的
mToken = token;
mIdent = ident;
mApplication = application;
mIntent = intent;
mReferrer = referrer;
mComponent = intent.getComponent();
mActivityInfo = info;
mTitle = title;
mParent = parent;
mEmbeddedID = id;
mLastNonConfigurationInstances = lastNonConfigurationInstances;
if (voiceInteractor != null) {
if (lastNonConfigurationInstances != null) {
mVoiceInteractor = lastNonConfigurationInstances.voiceInteractor;
} else {
mVoiceInteractor = new VoiceInteractor(voiceInteractor, this, this,
Looper.myLooper());
}
}
// 為該acitivity的窗口Window設(shè)置WindowManager對(duì)象,實(shí)際是WindowManagerImpl對(duì)象
mWindow.setWindowManager(
(WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
mToken, mComponent.flattenToString(),
(info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
if (mParent != null) {
mWindow.setContainer(mParent.getWindow());
}
mWindowManager = mWindow.getWindowManager();
mCurrentConfig = config;
}
- 可以看到,在這里 mWindow = new PhoneWindow(this) 為當(dāng)前acitivity生成了一個(gè)Window窗口;
- mWindow.setCallback(this);為Window對(duì)象設(shè)置一個(gè)Callback回調(diào)對(duì)象,這里是acitivity對(duì)象本身,因?yàn)槠鋵?shí)現(xiàn)Window.Callback接口;
- 最后為mWindow對(duì)象設(shè)置了一個(gè)WindowManager成員對(duì)象,同時(shí)引用賦值給當(dāng)前acitivity對(duì)象;
S4: PhoneWindow的生成相關(guān)
PhoneWindow extends Window
public PhoneWindow(Context context) {
super(context);
mLayoutInflater = LayoutInflater.from(context);
}
public Window(Context context) {
mContext = context;
mFeatures = mLocalFeatures = getDefaultFeatures(context);
}
- PhoneWindow構(gòu)造函數(shù),主要是得到當(dāng)前Context的引用,并通過(guò)LayoutInflater.from(context)得到一個(gè)PhoneLayoutInflater對(duì)象,用于后續(xù)通過(guò)資源id生成view對(duì)象.
- 這里看到LayoutInflater.from(context)和 mWindow.setWindowManager(...)中都調(diào)用了context.getSystemService(),實(shí)際在ActivityThread.performLaunchActivity()中生成acitivity對(duì)象后創(chuàng)建了一個(gè)ContextImpl對(duì)象并且在Activity.attach()中賦值給Activity的Context mBase成員;
S5: ContextImpl.getSystemService()
@Override
public Object getSystemService(String name) {
return SystemServiceRegistry.getSystemService(this, name);
}
// 看下具體去拿服務(wù)的類(lèi)
final class SystemServiceRegistry {
/**
* Gets a system service from a given context.
*/
public static Object getSystemService(ContextImpl ctx, String name) {
ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
return fetcher != null ? fetcher.getService(ctx) : null;
}
/**
* Statically registers a system service with the context.
* This method must be called during static initialization only.
*/
private static <T> void registerService(String serviceName, Class<T> serviceClass,
ServiceFetcher<T> serviceFetcher) {
SYSTEM_SERVICE_NAMES.put(serviceClass, serviceName);
SYSTEM_SERVICE_FETCHERS.put(serviceName, serviceFetcher);
}
private static final HashMap<Class<?>, String> SYSTEM_SERVICE_NAMES =
new HashMap<Class<?>, String>();
private static final HashMap<String, ServiceFetcher<?>> SYSTEM_SERVICE_FETCHERS =
new HashMap<String, ServiceFetcher<?>>();
private static int sServiceCacheSize;
// Not instantiable.
private SystemServiceRegistry() { }
static {
....
registerService(Context.LAYOUT_INFLATER_SERVICE, LayoutInflater.class,
new CachedServiceFetcher<LayoutInflater>() {
@Override
public LayoutInflater createService(ContextImpl ctx) {
// 具體生成的對(duì)象是個(gè)PhoneLayoutInflater
return new PhoneLayoutInflater(ctx.getOuterContext());
}});
registerService(Context.WINDOW_SERVICE, WindowManager.class,
new CachedServiceFetcher<WindowManager>() {
@Override
public WindowManager createService(ContextImpl ctx) {
// 具體生成的對(duì)象是個(gè)WindowManagerImpl
return new WindowManagerImpl(ctx.getDisplay());
}});
....
}
}
static abstract interface ServiceFetcher<T> {
T getService(ContextImpl ctx);
}
/**
* Override this class when the system service constructor needs a
* ContextImpl and should be cached and retained by that context.
*/
static abstract class CachedServiceFetcher<T> implements ServiceFetcher<T> {
private final int mCacheIndex;
public CachedServiceFetcher() {
mCacheIndex = sServiceCacheSize++;
}
@Override
@SuppressWarnings("unchecked")
public final T getService(ContextImpl ctx) {
final Object[] cache = ctx.mServiceCache;
synchronized (cache) {
// Fetch or create the service.
Object service = cache[mCacheIndex];
if (service == null) {
service = createService(ctx);
cache[mCacheIndex] = service;
}
return (T)service;
}
}
public abstract T createService(ContextImpl ctx);
}
很明顯,通過(guò)LayoutInflater.from(context)得到的是一個(gè)PhoneLayoutInflater對(duì)象,通過(guò)context.getSystemService(Context.WINDOW_SERVICE)是一個(gè)WindowManagerImpl對(duì)象
S6: Window.setWindowManager()
/**
* Set the window manager for use by this Window to, for example,
* display panels. This is <em>not</em> used for displaying the
* Window itself -- that must be done by the client.
*
* @param wm The window manager for adding new windows.
*/
public void setWindowManager(WindowManager wm, IBinder appToken, String appName) {
setWindowManager(wm, appToken, appName, false);
}
/**
* Set the window manager for use by this Window to, for example,
* display panels. This is <em>not</em> used for displaying the
* Window itself -- that must be done by the client.
*
* @param wm The window manager for adding new windows.
*/
public void setWindowManager(WindowManager wm, IBinder appToken, String appName,
boolean hardwareAccelerated) {
mAppToken = appToken;
mAppName = appName;
mHardwareAccelerated = hardwareAccelerated
|| SystemProperties.getBoolean(PROPERTY_HARDWARE_UI, false);
if (wm == null) {
wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
}
mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
}
很明顯,參數(shù)wm是剛才獲取的WindowManagerImpl對(duì)象,appToken是當(dāng)前acitivity的一個(gè)標(biāo)記特征對(duì)象,實(shí)際最初是ActivityStackSupervisor.startActivityLocked()中生成ActivityRecord對(duì)象時(shí)候生成的一個(gè)IApplicationToken.Stub對(duì)象,看下WindowManagerImpl.createLocalWindowManager()
public final class WindowManagerImpl implements WindowManager {
....
private final Display mDisplay;
private final Window mParentWindow;
public WindowManagerImpl createLocalWindowManager(Window parentWindow) {
return new WindowManagerImpl(mDisplay, parentWindow);
}
}
生成一個(gè)新的當(dāng)前WindowManagerImpl對(duì)象,成員變量Display mDisplay指向當(dāng)前的WindowManagerImpl對(duì)象,成員變量Window mParentWindow指向了當(dāng)前window;
至此,已經(jīng)為當(dāng)前acitivity生成了一個(gè)window,同時(shí)為這個(gè)window設(shè)置了當(dāng)前acitivity作為CallBack回調(diào),同時(shí)為window設(shè)置了一個(gè)WindowManagerImpl管理對(duì)象,且acitivity也拿到了這個(gè)管理對(duì)象;接下來(lái)在activity.attach()之后就會(huì)調(diào)用生命周期的onCreate()方法,一般情況在其中調(diào)用setContentView()
S7: Activity.setContentView()
public void setContentView(@LayoutRes int layoutResID) {
getWindow().setContentView(layoutResID);
initWindowDecorActionBar();
}
直接進(jìn)入activity關(guān)聯(lián)的PhoneWindow中為之設(shè)置view視圖
S8: PhoneWindow.setContentView()
@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.
// 第一次進(jìn)來(lái)mContentParent默認(rèn)為null,先去構(gòu)造頂層的容器View
if (mContentParent == null) {
installDecor();
} else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
mContentParent.removeAllViews();
}
if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
getContext());
transitionTo(newScene);
} else {
// 在頂層容器View中通過(guò)inflate()為之生成視圖樹(shù)體系
mLayoutInflater.inflate(layoutResID, mContentParent);
}
mContentParent.requestApplyInsets();
final Callback cb = getCallback();
if (cb != null && !isDestroyed()) {
cb.onContentChanged();
}
}
// 初試化window的直接View容器DecorView mDecor,實(shí)際是一個(gè)FrameLayout,之后獲取到
// id==Window.D_ANDROID_CONTENT的視圖內(nèi)容容器ViewGroup mContentParent
private void installDecor() {
if (mDecor == null) {
// 生成一個(gè)DecorView對(duì)象
mDecor = generateDecor();
mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
mDecor.setIsRootNamespace(true);
if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
}
}
if (mContentParent == null) {
mContentParent = generateLayout(mDecor);
}
....
}
// DecorView extends FrameLayout
protected DecorView generateDecor() {
return new DecorView(getContext(), -1);
}
protected ViewGroup generateLayout(DecorView decor) {
....
int layoutResource;
int features = getLocalFeatures();
// System.out.println("Features: 0x" + Integer.toHexString(features));
// 根據(jù)window特性獲取將要生成的view的系統(tǒng)資源id
if ((features & (1 << FEATURE_SWIPE_TO_DISMISS)) != 0) {
layoutResource = R.layout.screen_swipe_dismiss;
} else if ((features & ((1 << FEATURE_LEFT_ICON) | (1 << FEATURE_RIGHT_ICON))) != 0) {
if (mIsFloating) {
TypedValue res = new TypedValue();
getContext().getTheme().resolveAttribute(
R.attr.dialogTitleIconsDecorLayout, res, true);
layoutResource = res.resourceId;
} else {
layoutResource = 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 = 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(
R.attr.dialogCustomTitleDecorLayout, res, true);
layoutResource = res.resourceId;
} else {
layoutResource = R.layout.screen_custom_title;
}
// XXX Remove this once action bar supports these features.
removeFeature(FEATURE_ACTION_BAR);
} else if ((features & (1 << FEATURE_NO_TITLE)) == 0) {
// If no other features and not embedded, only need a title.
// If the window is floating, we need a dialog layout
if (mIsFloating) {
TypedValue res = new TypedValue();
getContext().getTheme().resolveAttribute(
R.attr.dialogTitleDecorLayout, res, true);
layoutResource = res.resourceId;
} else if ((features & (1 << FEATURE_ACTION_BAR)) != 0) {
layoutResource = a.getResourceId(
R.styleable.Window_windowActionBarFullscreenDecorLayout,
R.layout.screen_action_bar);
} else {
layoutResource = R.layout.screen_title;
}
// System.out.println("Title!");
} else if ((features & (1 << FEATURE_ACTION_MODE_OVERLAY)) != 0) {
layoutResource = R.layout.screen_simple_overlay_action_mode;
} else {
// Embedded, so no decoration is needed.
layoutResource = R.layout.screen_simple;
// System.out.println("Simple!");
}
// 將上面得到的系統(tǒng)View資源id生成view,把a(bǔ)ddView()添加到頂層容器DecorView中
View in = mLayoutInflater.inflate(layoutResource, null);
decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
mContentRoot = (ViewGroup) in;
// 在前面生成的頂層容器DecorView mDecor中遍歷找到ID==com.android.internal.R.id.content的View作為視圖內(nèi)容容器并返回
ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
....
return contentParent;
}
- 至此,已經(jīng)在activity的onCreate()中為window設(shè)置了視圖,并將setContentView()中的view通過(guò)ViewGroup.addView()關(guān)聯(lián)到window的頂層視圖容器DecorView中.
- 接下來(lái)回看ActivityThread.handleLaunchActivity()中,會(huì)調(diào)用handleResumeActivity()方法做進(jìn)一步操作
S9: ActivityThread.handleResumeActivity()
final void handleResumeActivity(IBinder token,
boolean clearHide, boolean isForward, boolean reallyResume) {
....
// 主要為當(dāng)前acitivity關(guān)聯(lián)的ActivityClientRecord對(duì)象做一些變量賦值操作,同時(shí)也
// 調(diào)用了Activity生命周期的onResume()方法
// 當(dāng)前acitivity關(guān)聯(lián)的ActivityClientRecord對(duì)象是在ActivityThread.performLaunchActivity()中
// 保存在ActivityThread的final ArrayMap<IBinder, ActivityClientRecord> mActivities變量中.
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.
// 這里主要判斷當(dāng)前acitivity是否去啟動(dòng)別的acitivity了,沒(méi)有的話表明此acitivity即將
// 要顯示出來(lái),willBeVisible == true
boolean willBeVisible = !a.mStartedActivity;
if (!willBeVisible) {
try {
// 通過(guò)Binder機(jī)制跳到ActivityManagerService中看當(dāng)前acitivity所在的
// ActivityStack中是否有位于當(dāng)前acitivity之上的activity是否全屏的,是的話返回false
willBeVisible = ActivityManagerNative.getDefault().willActivityBeVisible(
a.getActivityToken());
} catch (RemoteException e) {
}
}
// 這里r.window沒(méi)有賦值當(dāng)然為null,activity.mFinished==fale,并且要顯示的話進(jìn)入if
if (r.window == null && !a.mFinished && willBeVisible) {
// 已經(jīng)在acitivity.attach()中生成管理window,且在setContentView()中為window設(shè)置好了視圖
r.window = r.activity.getWindow();
View decor = r.window.getDecorView();
decor.setVisibility(View.INVISIBLE);
// 由S6中可知道,acitivity和window的WindowManager對(duì)象實(shí)際是WindowManagerImpl
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;
// 關(guān)聯(lián)視圖View和WindowManager
wm.addView(decor, l);
}
....
}
// 上面r.window.getAttributes()獲取的是window默認(rèn)的mWindowAttributes = new WindowManager.LayoutParams(),
public LayoutParams() {
// 默認(rèn)無(wú)參構(gòu)造函數(shù)LayoutParams.width和LayoutParams.height均為L(zhǎng)ayoutParams.MATCH_PARENT
super(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
type = TYPE_APPLICATION;
format = PixelFormat.OPAQUE;
}
至此,window的視圖容器和WindowManager還未關(guān)聯(lián)起來(lái),下面看如何調(diào)用WindowManagerImpl.addView()關(guān)聯(lián)的.
S10: WindowManagerImpl.addView()
public final class WindowManagerImpl implements WindowManager {
private final Display mDisplay;
private final Window mParentWindow;
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);
}
....
}
由S6可知,這里的mParentWindow即是當(dāng)前acitivity關(guān)聯(lián)的window對(duì)象,由S5可知,mDisplay是與acitivity關(guān)聯(lián)的ContextImpl對(duì)象獲取的Display對(duì)象.
S11: WindowManagerGlobal.addView()
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);
}
// 判斷當(dāng)前的activity關(guān)聯(lián)的window中的頂層視圖DecorView是否已經(jīng)設(shè)置并關(guān)聯(lián)過(guò)一個(gè)ViewRootImpl了
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);
}
}
}
// 為當(dāng)前acitivity的關(guān)聯(lián)window的頂層視圖DecorView生成一個(gè)最頂層視圖控制器ViewParent
// 在Activity.attach()中生成window對(duì)象的時(shí)候傳入的Context是acitivity本身,之后
// window中生成頂層視圖DecorView的時(shí)候用的Context也是這個(gè)acitivity本身
root = new ViewRootImpl(view.getContext(), display);
view.setLayoutParams(wparams);
// 分別保存到WindowManagerGlobal的3個(gè)ArrayList中
mViews.add(view);
mRoots.add(root);
mParams.add(wparams);
}
// do this last because it fires off messages to start doing things
try {
// 進(jìn)入最頂層ViewParent視圖控制器去做最后的關(guān)聯(lián)設(shè)置
root.setView(view, wparams, panelParentView);
} catch (RuntimeException e) {
// BadTokenException or InvalidDisplayException, clean up.
synchronized (mLock) {
final int index = findViewLocked(view, false);
if (index >= 0) {
removeViewLocked(index, true);
}
}
throw e;
}
}
看下這里的view.setLayoutParams(wparams);即給當(dāng)前acitivity的關(guān)聯(lián)window的頂層視圖DecorView設(shè)置LayoutParams參數(shù)
public void setLayoutParams(ViewGroup.LayoutParams params) {
if (params == null) {
throw new NullPointerException("Layout parameters cannot be null");
}
mLayoutParams = params;
resolveLayoutParams();
if (mParent instanceof ViewGroup) {
((ViewGroup) mParent).onSetLayoutParams(this, params);
}
requestLayout();
}
@CallSuper
public void requestLayout() {
if (mMeasureCache != null) mMeasureCache.clear();
// 這個(gè)時(shí)候該View還沒(méi)有與ViewRootImpl最頂層控制器關(guān)聯(lián),故mAttachInfo==null
if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
// Only trigger request-during-layout logic if this is the view requesting it,
// not the views in its parent hierarchy
ViewRootImpl viewRoot = getViewRootImpl();
if (viewRoot != null && viewRoot.isInLayout()) {
if (!viewRoot.requestLayoutDuringLayout(this)) {
return;
}
}
mAttachInfo.mViewRequestingLayout = this;
}
// 設(shè)置標(biāo)記要強(qiáng)制走layout和draw
mPrivateFlags |= PFLAG_FORCE_LAYOUT;
mPrivateFlags |= PFLAG_INVALIDATED;
// 同mAttachInfo,這個(gè)時(shí)候mParent==null
if (mParent != null && !mParent.isLayoutRequested()) {
mParent.requestLayout();
}
if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
mAttachInfo.mViewRequestingLayout = null;
}
}
S12: ViewRootImpl.setView()
// 先看下ViewRootImpl的構(gòu)造函數(shù)初始化
public ViewRootImpl(Context context, Display display) {
// 由S11可知,這個(gè)context就是當(dāng)前的acitivity對(duì)象本身
mContext = context;
// 與WindowManagerService關(guān)聯(lián)的一個(gè)重要對(duì)象,主要用于關(guān)聯(lián)當(dāng)前視圖和系統(tǒng)WindowManagerService的通訊
mWindowSession = WindowManagerGlobal.getWindowSession();
mDisplay = display;
mBasePackageName = context.getBasePackageName();
mDisplayAdjustments = display.getDisplayAdjustments();
mThread = Thread.currentThread();
mLocation = new WindowLeaked(null);
mLocation.fillInStackTrace();
mWidth = -1;
mHeight = -1;
mDirty = new Rect();
mTempRect = new Rect();
mVisRect = new Rect();
mWinFrame = new Rect();
// 當(dāng)前視圖的一個(gè)IWindow.Stub對(duì)象,等下面與系統(tǒng)WindowManagerService關(guān)聯(lián)時(shí)候用到,表征了當(dāng)前的視圖窗體
mWindow = new W(this);
mTargetSdkVersion = context.getApplicationInfo().targetSdkVersion;
mViewVisibility = View.GONE;
mTransparentRegion = new Region();
mPreviousTransparentRegion = new Region();
mFirst = true; // true for the first time the view is added
mAdded = false;
// 這里生成View視圖樹(shù)的AttachInfo對(duì)象
mAttachInfo = new View.AttachInfo(mWindowSession, mWindow, display, this, mHandler, this);
mAccessibilityManager = AccessibilityManager.getInstance(context);
mAccessibilityInteractionConnectionManager =
new AccessibilityInteractionConnectionManager();
mAccessibilityManager.addAccessibilityStateChangeListener(
mAccessibilityInteractionConnectionManager);
mHighContrastTextManager = new HighContrastTextManager();
mAccessibilityManager.addHighTextContrastStateChangeListener(
mHighContrastTextManager);
mViewConfiguration = ViewConfiguration.get(context);
mDensity = context.getResources().getDisplayMetrics().densityDpi;
mNoncompatDensity = context.getResources().getDisplayMetrics().noncompatDensityDpi;
mFallbackEventHandler = new PhoneFallbackEventHandler(context);
// 重要的顯示刷新幀處理對(duì)象,在調(diào)用requestLayout()刷新視圖的時(shí)候用到了
mChoreographer = Choreographer.getInstance();
mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
loadSystemProperties();
}
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
synchronized (this) {
if (mView == null) {
mView = view;
mAttachInfo.mDisplayState = mDisplay.getState();
mDisplayManager.registerDisplayListener(mDisplayListener, mHandler);
mViewLayoutDirectionInitial = mView.getRawLayoutDirection();
mFallbackEventHandler.setView(view);
mWindowAttributes.copyFrom(attrs);
if (mWindowAttributes.packageName == null) {
mWindowAttributes.packageName = mBasePackageName;
}
attrs = mWindowAttributes;
// Keep track of the actual window flags supplied by the client.
mClientWindowLayoutFlags = attrs.flags;
setAccessibilityFocus(null, null);
if (view instanceof RootViewSurfaceTaker) {
mSurfaceHolderCallback =
((RootViewSurfaceTaker)view).willYouTakeTheSurface();
if (mSurfaceHolderCallback != null) {
mSurfaceHolder = new TakenSurfaceHolder();
mSurfaceHolder.setFormat(PixelFormat.UNKNOWN);
}
}
// Compute surface insets required to draw at specified Z value.
// TODO: Use real shadow insets for a constant max Z.
if (!attrs.hasManualSurfaceInsets) {
final int surfaceInset = (int) Math.ceil(view.getZ() * 2);
attrs.surfaceInsets.set(surfaceInset, surfaceInset, surfaceInset, surfaceInset);
}
CompatibilityInfo compatibilityInfo = mDisplayAdjustments.getCompatibilityInfo();
mTranslator = compatibilityInfo.getTranslator();
// If the application owns the surface, don't enable hardware acceleration
if (mSurfaceHolder == null) {
enableHardwareAcceleration(attrs);
}
boolean restore = false;
if (mTranslator != null) {
mSurface.setCompatibilityTranslator(mTranslator);
restore = true;
attrs.backup();
mTranslator.translateWindowLayout(attrs);
}
if (DEBUG_LAYOUT) Log.d(TAG, "WindowLayout in setView:" + attrs);
if (!compatibilityInfo.supportsScreen()) {
attrs.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
mLastInCompatMode = true;
}
mSoftInputMode = attrs.softInputMode;
mWindowAttributesChanged = true;
mWindowAttributesChangesFlag = WindowManager.LayoutParams.EVERYTHING_CHANGED;
// 賦值根view
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.
// 去發(fā)起與該ViewRootImpl關(guān)聯(lián)的視圖樹(shù)的測(cè)量,布局,繪制等操作
requestLayout();
// 這里一般前面沒(méi)有設(shè)置特別設(shè)置過(guò)mWindowAttributes.inputFeatures,所以if()為true
// 一般情況我們不會(huì)設(shè)置當(dāng)前窗口不接受任何輸入事件
if ((mWindowAttributes.inputFeatures
& WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
mInputChannel = new InputChannel();
}
try {
mOrigWindowType = mWindowAttributes.type;
mAttachInfo.mRecomputeGlobalAttributes = true;
collectViewAttributes();
// 關(guān)聯(lián)設(shè)置當(dāng)前視圖和WindowManagerService
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);
throw new RuntimeException("Adding window failed", e);
} finally {
if (restore) {
attrs.restore();
}
}
if (mTranslator != null) {
mTranslator.translateRectInScreenToAppWindow(mAttachInfo.mContentInsets);
}
mPendingOverscanInsets.set(0, 0, 0, 0);
mPendingContentInsets.set(mAttachInfo.mContentInsets);
mPendingStableInsets.set(mAttachInfo.mStableInsets);
mPendingVisibleInsets.set(0, 0, 0, 0);
if (DEBUG_LAYOUT) Log.v(TAG, "Added window " + mWindow);
// 前面關(guān)聯(lián)當(dāng)前視圖和WindowManagerService失敗了,拋出異常,中斷程序
if (res < WindowManagerGlobal.ADD_OKAY) {
mAttachInfo.mRootView = null;
mAdded = false;
mFallbackEventHandler.setView(null);
unscheduleTraversals();
setAccessibilityFocus(null, null);
switch (res) {
case WindowManagerGlobal.ADD_BAD_APP_TOKEN:
case WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN:
throw new WindowManager.BadTokenException(
"Unable to add window -- token " + attrs.token
+ " is not valid; is your activity running?");
case WindowManagerGlobal.ADD_NOT_APP_TOKEN:
throw new WindowManager.BadTokenException(
"Unable to add window -- token " + attrs.token
+ " is not for an application");
case WindowManagerGlobal.ADD_APP_EXITING:
throw new WindowManager.BadTokenException(
"Unable to add window -- app for token " + attrs.token
+ " is exiting");
case WindowManagerGlobal.ADD_DUPLICATE_ADD:
throw new WindowManager.BadTokenException(
"Unable to add window -- window " + mWindow
+ " has already been added");
case WindowManagerGlobal.ADD_STARTING_NOT_NEEDED:
// Silently ignore -- we would have just removed it
// right away, anyway.
return;
case WindowManagerGlobal.ADD_MULTIPLE_SINGLETON:
throw new WindowManager.BadTokenException(
"Unable to add window " + mWindow +
" -- another window of this type already exists");
case WindowManagerGlobal.ADD_PERMISSION_DENIED:
throw new WindowManager.BadTokenException(
"Unable to add window " + mWindow +
" -- permission denied for this window type");
case WindowManagerGlobal.ADD_INVALID_DISPLAY:
throw new WindowManager.InvalidDisplayException(
"Unable to add window " + mWindow +
" -- the specified display can not be found");
case WindowManagerGlobal.ADD_INVALID_TYPE:
throw new WindowManager.InvalidDisplayException(
"Unable to add window " + mWindow
+ " -- the specified window type is not valid");
}
throw new RuntimeException(
"Unable to add window -- unknown error code " + res);
}
if (view instanceof RootViewSurfaceTaker) {
mInputQueueCallback =
((RootViewSurfaceTaker)view).willYouTakeTheInputQueue();
}
// 一般情況前面已經(jīng)初始化了mInputChannel對(duì)象
if (mInputChannel != null) {
if (mInputQueueCallback != null) {
mInputQueue = new InputQueue();
mInputQueueCallback.onInputQueueCreated(mInputQueue);
}
// 重要,這里為當(dāng)前窗口生成了應(yīng)該WindowInputEventReceiver即窗口事件的分發(fā)接受者
// 一般各種屏幕觸摸等事件最開(kāi)始由本地代碼調(diào)用java層WindowInputEventReceiver類(lèi)的onInputEvent方法處理
mInputEventReceiver = new WindowInputEventReceiver(mInputChannel,
Looper.myLooper());
}
// 為window的頂層View即其DecorView mDecor關(guān)聯(lián)一個(gè)ViewParent即當(dāng)前的ViewRootImpl對(duì)象
view.assignParent(this);
mAddedTouchMode = (res & WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE) != 0;
mAppVisible = (res & WindowManagerGlobal.ADD_FLAG_APP_VISIBLE) != 0;
if (mAccessibilityManager.isEnabled()) {
mAccessibilityInteractionConnectionManager.ensureConnection();
}
if (view.getImportantForAccessibility() == View.IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
view.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
}
// Set up the input pipeline.
CharSequence counterSuffix = attrs.getTitle();
mSyntheticInputStage = new SyntheticInputStage();
InputStage viewPostImeStage = new ViewPostImeInputStage(mSyntheticInputStage);
InputStage nativePostImeStage = new NativePostImeInputStage(viewPostImeStage,
"aq:native-post-ime:" + counterSuffix);
InputStage earlyPostImeStage = new EarlyPostImeInputStage(nativePostImeStage);
InputStage imeStage = new ImeInputStage(earlyPostImeStage,
"aq:ime:" + counterSuffix);
InputStage viewPreImeStage = new ViewPreImeInputStage(imeStage);
InputStage nativePreImeStage = new NativePreImeInputStage(viewPreImeStage,
"aq:native-pre-ime:" + counterSuffix);
// 設(shè)置各種窗口事件的分發(fā)至當(dāng)前window視圖的處理對(duì)象,比如View的touch觸摸事件一般分發(fā)至ViewPostImeInputStage處理
mFirstInputStage = nativePreImeStage;
mFirstPostImeInputStage = earlyPostImeStage;
mPendingInputEventQueueLengthCounterName = "aq:pending:" + counterSuffix;
}
}
}
由上面可知,ViewRootImpl的setView()方法主要做了兩件事:1是調(diào)用requestLayout()去測(cè)量,布局,繪制當(dāng)前視圖;2是為當(dāng)前窗體關(guān)聯(lián)到了WindowManagerService系統(tǒng)服務(wù),并初始化了當(dāng)前視圖接受到屏幕一些事件的分發(fā)處理對(duì)象.
S13: ViewRootImpl.requestLayout()
@Override
public void requestLayout() {
if (!mHandlingLayoutInLayoutRequest) {
// 非主線程調(diào)用的話即拋出異常,所以平時(shí)調(diào)用View.requestLayout()一定要在主線程調(diào)用
checkThread();
mLayoutRequested = true;
scheduleTraversals();
}
}
void scheduleTraversals() {
if (!mTraversalScheduled) {
mTraversalScheduled = true;
// 這里mHandler使用的當(dāng)前程序主線程的Looper,這里在在當(dāng)前程序的主線程的消息隊(duì)列MessageQueue中插
// 入一個(gè)同步欄柵,讓異步消息優(yōu)先調(diào)用
mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
// 這里最后是向主線程消息隊(duì)列中放了一個(gè)異步消息,并最終在主線程Looper循環(huán)中調(diào)用mTraversalRunnable.run()方法
mChoreographer.postCallback(
Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
if (!mUnbufferedInputDispatch) {
scheduleConsumeBatchedInput();
}
notifyRendererOfFramePending();
pokeDrawLockIfNeeded();
}
}
final class TraversalRunnable implements Runnable {
@Override
public void run() {
doTraversal();
}
}
void doTraversal() {
if (mTraversalScheduled) {
mTraversalScheduled = false;
// 移除主線程消息隊(duì)列的前面插入的欄柵,讓消息隊(duì)列中的非異步的消息正常分發(fā)調(diào)用
mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);
if (mProfile) {
Debug.startMethodTracing("ViewAncestor");
}
// 真正地去走視圖樹(shù)的測(cè)量,布局,繪制和顯示去了
performTraversals();
if (mProfile) {
Debug.stopMethodTracing();
mProfile = false;
}
}
}
一般情況,我們?cè)贏ctivity的生命周期的調(diào)用Handler.post()或者View.post()方法,都是向主線程的消息隊(duì)列中放了一個(gè)同步消息,而同步消息是受到消息隊(duì)列是否插入同步欄柵過(guò)濾影響的,而ViewRootImpe中讓視圖繪制布局顯示的是向消息隊(duì)列放了一個(gè)異步消息,且在之前插入了一個(gè)同步欄柵過(guò)濾非異步的消息對(duì)象,所以一般情況,都是ViewRootImpe.performTraversals()優(yōu)先調(diào)用.這也是為何我們?cè)贏ctivity.onCreate()調(diào)用Handler.post()就可以拿到某個(gè)View的寬高的原因.
至此,從源碼中分析了Activity生成之后到其視圖窗口的生成,測(cè)量,布局,繪制的中間過(guò)程
- Android 6.0 & API Level 23
- Github: Nvsleep
- 郵箱: lizhenqiao@126.com