一欢策、相關(guān)概念
1、ActivityThread:為應(yīng)用程序的主線程類,所有的APK程序都有且僅有一個(gè)ActivityThread掠哥,程序的入口為該類static main()函數(shù)
Activity:Activity包含一個(gè)Window,該Window在Activity的attach方法中通過調(diào)用new PhoneWindow()創(chuàng)建一個(gè)window;
2稚叹、PhoneWindow:繼承Window類,是把一個(gè)FrameLayout進(jìn)行一定的包裝拿诸,并提供了一組通用的窗口操作接口扒袖,內(nèi)部包含一個(gè)DecorView
3、View:最基本的UI組件亩码,表示屏幕上的一個(gè)矩形區(qū)域季率;
4、DecorView:該類是一個(gè) FrameLayout 的子類蟀伸,并且是 PhoneWindow 中的一個(gè)內(nèi)部類蚀同。Decor的英文是 Decoration缅刽,即“修飾”的意思,DecorView 就是對(duì)普通的 FrameLayout 進(jìn)行了一定的修飾蠢络,比如添加一個(gè)通用的 Title bar衰猛,并響應(yīng)特定的按鍵消息等。刹孔;
5啡省、Window:表示頂層窗口,管理界面的顯示和事件的響應(yīng)髓霞;每個(gè)Activity 均會(huì)創(chuàng)建一個(gè)PhoneWindow對(duì)象卦睹,是Activity和整個(gè)View系統(tǒng)交互的接口,該類提供了一組通用的窗口(Window)操作 API方库,這里的窗口僅僅是程序?qū)用嫔系慕嵝颍琖MS 所管理的窗口并不是 Window 類,而是一個(gè) View 或者 ViewGroup 類纵潦,一般就是指DecorView 類徐鹤,即一個(gè) DecorView 就是 WmS 所管理的一個(gè)窗口。Window 是一個(gè) abstract 類型邀层。
6返敬、WindowManager:一個(gè)interface,繼承自ViewManager寥院。所在應(yīng)用進(jìn)程的窗口管理器劲赠;有一個(gè)implementation WindowManagerImpl;
主要用來管理窗口的一些狀態(tài)秸谢、屬性凛澎、view增加、刪除估蹄、更新预厌、窗口順序、消息收集和處理等元媚。
7、ViewRootImpl:通過IWindowSession接口與全局窗口管理器進(jìn)行交互:界面控制和消息響應(yīng)苗沧;WMS 管理客戶端窗口時(shí)刊棕,需要通知客戶端進(jìn)行某種操作,這些都是通過異步消息完成的
二待逞、步驟
Step1:
當(dāng)啟動(dòng)Activity時(shí)甥角,system_server進(jìn)程通過AMS(ActivityManagerService)的遠(yuǎn)程代理ApplicationThreadProxy(即應(yīng)用進(jìn)程的Binder,IApplicationThread)的scheduleLaunchActivit(),標(biāo)示SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION识樱,底層binder驅(qū)動(dòng)啟動(dòng)應(yīng)用進(jìn)程XXXActivity嗤无,到應(yīng)用進(jìn)程的ActivityThread的內(nèi)部類ApplicationThread的父類ApplicationNative的onTransact震束,再到scheduleLaunchActivity().
Step2:
ApplicationThread的scheduleLaunchActivity:通過sendMessage(H.LAUNCH_ACTIVITY, r),發(fā)到UI線程的ActivityThread 的H處理即handleLaunchActivity:
ActivityThread.java
public final class ActivityThread {
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
// Initialize before creating the activity
WindowManagerGlobal.initialize();
Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
reportSizeConfigurations(r);
Bundle oldState = r.state;
handleResumeActivity(r.token, false, r.isForward,
!r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
...
}
}
}
其中WindowManagerGlobal.initialize;是先取到WMS(WindowManagerService)的遠(yuǎn)程代理IWindowManager
WindowManagerGlobal.java
public final class WindowManagerGlobal {
public static void initialize() {
getWindowManagerService();
}
public static IWindowManager getWindowManagerService() {
synchronized (WindowManagerGlobal.class) {
if (sWindowManagerService == null) {
sWindowManagerService = IWindowManager.Stub.asInterface(
ServiceManager.getService("window"));
try {
sWindowManagerService = getWindowManagerService();
ValueAnimator.setDurationScale(sWindowManagerService.getCurrentAnimatorScale());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
return sWindowManagerService;
}
}
}
Activity a = performLaunchActivity(r, customIntent);使用ClassLoader加載XXXActivity当犯,這其中會(huì)創(chuàng)建ContextImpl垢村、如果Application還沒啟動(dòng)過,會(huì)先把Applicaition創(chuàng)建并onCreate,然后調(diào)用XXXActivity的attach();
在attach中:會(huì)創(chuàng)建改activity的對(duì)應(yīng)的window即PhoneWindow嚎卫,以及phoneWindow和WindowManagerImpl關(guān)聯(lián):
Activity:
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,
Window window) {
attachBaseContext(context);
mFragments.attachHost(null /*parent*/);
mWindow = new PhoneWindow(this, window);
mWindow.setWindowControllerCallback(this);
mWindow.setCallback(this);
mWindow.setOnWindowDismissedCallback(this);
mWindow.getLayoutInflater().setPrivateFactory(this);
mMainThread = aThread;
mInstrumentation = instr;
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;
}
其中:(WindowManager)context.getSystemService(Context.WINDOW_SERVICE)獲取到是WindowManagerImpl:
這邊會(huì)走到ContextImpl.getSystemService:
class ContextImpl extends Context {
@Override
public Object getSystemService(String name) {
return SystemServiceRegistry.getSystemService(this, name);
}
}
SystemServiceRegistry:
final class SystemServiceRegistry {
public static Object getSystemService(ContextImpl ctx, String name) {
ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
return fetcher != null ? fetcher.getService(ctx) : null;
}
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;
static {
registerService(Context.ACCESSIBILITY_SERVICE, AccessibilityManager.class,
new CachedServiceFetcher<AccessibilityManager>() {
@Override
public AccessibilityManager createService(ContextImpl ctx) {
return AccessibilityManager.getInstance(ctx);
}});
registerService(Context.WINDOW_SERVICE, WindowManager.class,
new CachedServiceFetcher<WindowManager>() {
@Override
public WindowManager createService(ContextImpl ctx) {
return new WindowManagerImpl(ctx);
}});
}
返回是new WindowManagerImpl(ctx);在performLaunchActivity函數(shù)中嘉栓,走完attach后,繼續(xù)調(diào)用mInstrumentation.callActivityOnCreate去實(shí)行XXXActivity的onCreate拓诸,這時(shí)候大家會(huì)寫setContentView(R.layout.xxx)
Step3:
Activity.setContentView():
會(huì)調(diào)用getWindow().setContentView(layoutResID),即PhoneWindow類中的setContentView:主要是在PhoneWindow創(chuàng)建DecorView mDecor(This is the top-level view of the window, containing the window decor),然后從mDecor找出android.R.id.content: mContentParent(ViewGroup), 然后把a(bǔ)ctivity設(shè)置的View添加到mContentParent.addView(view, params);
public void setContentView(@LayoutRes int layoutResID) {
getWindow().setContentView(layoutResID);
initWindowDecorActionBar();
}
PhoneWindow:
public class PhoneWindow extends Window implements MenuBuilder.Callback {
public void setContentView(int layoutResID) {
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 {
mLayoutInflater.inflate(layoutResID, mContentParent);
}
mContentParent.requestApplyInsets();
final Callback cb = getCallback();
if (cb != null && !isDestroyed()) {
cb.onContentChanged();
}
mContentParentExplicitlySet = true;
}
}
Step4:
在ActivitThread.handleLaunchActivity函數(shù)走完performLaunchActivity后侵佃,接著走h(yuǎn)andleResumeActivity函數(shù)中,顯示啟動(dòng)r = performResumeActivity(token, clearHide, reason);去走XXXActivity的onResume奠支。
接著會(huì)對(duì)Activity的對(duì)應(yīng)的window設(shè)置窗口類型:l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION馋辈,WMS是對(duì)窗口進(jìn)行操作,每個(gè)activity對(duì)應(yīng)一個(gè)窗口倍谜,F(xiàn)ramework會(huì)定義好幾種窗口類型迈螟,比如系統(tǒng)Window、應(yīng)用程序window枢劝、子Window等井联。這邊的type類型很重要,沒有這個(gè)您旁,window顯示不出來的烙常。
接著會(huì)調(diào)用到ViewManager wm = a.getWindowManager();wm.addView(decor, l);走到WindowManagerImpl.addView:
ActivityThread:
final void handleResumeActivity(IBinder token,
boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
ActivityClientRecord r = mActivities.get(token);
...
r = performResumeActivity(token, clearHide, reason);
...
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;
ViewRootImpl impl = decor.getViewRootImpl();
if (impl != null) {
impl.notifyChildRebuilt();
}
}
if (a.mVisibleFromClient && !a.mWindowAdded) {
a.mWindowAdded = true;
wm.addView(decor, l);
}
...
}
Step5:
WindowManagerImpl的addView又調(diào)用到WindowManagerGlobal.getInstance()的addView:
這個(gè)函數(shù)會(huì)創(chuàng)建root = new ViewRootImpl(view.getContext(), display);然后保存到mRoots.add(root)
接著調(diào)用到 root.setView(view, wparams, panelParentView);
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, mContext.getDisplay(), mParentWindow);
}
}
public final class WindowManagerGlobal {
public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow) {
...
ViewRootImpl root;
View panelParentView = null;
synchronized (mLock) {
...
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);
} catch (RuntimeException e) {
}
}
}
Step6:
ViewRootImpl.setView():
這個(gè)函數(shù)中,通過WindowManagerGloabl拿到IWindowSession mWindowSession及遠(yuǎn)程WMS的Seesion的對(duì)象鹤盒,進(jìn)行mWindowSession.addToDisplay蚕脏,到system_server進(jìn)程的Session中。
public final class ViewRootImpl implements ViewParent,
View.AttachInfo.Callbacks, ThreadedRenderer.HardwareDrawCallbacks {
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
synchronized (this) {
....
try {
res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
getHostVisibility(), mDisplay.getDisplayId(),
mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
mAttachInfo.mOutsets, mInputChannel);
}
}
...
}
}
這個(gè)mWindowSession是
public static IWindowSession getWindowSession() {
synchronized (WindowManagerGlobal.class) {
if (sWindowSession == null) {
try {
InputMethodManager imm = InputMethodManager.getInstance();
IWindowManager windowManager = getWindowManagerService();
sWindowSession = windowManager.openSession(
new IWindowSessionCallback.Stub() {
@Override
public void onAnimatorScaleChanged(float scale) {
ValueAnimator.setDurationScale(scale);
}
},
imm.getClient(), imm.getInputContext());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
return sWindowSession;
}
}
調(diào)用到WindowManagerService的openSession方法:
public class WindowManagerService extends IWindowManager.Stub
implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
@Override
public IWindowSession openSession(IWindowSessionCallback callback, IInputMethodClient client,
IInputContext inputContext) {
if (client == null) throw new IllegalArgumentException("null client");
if (inputContext == null) throw new IllegalArgumentException("null inputContext");
Session session = new Session(this, callback, client, inputContext);
return session;
}
}