Activity頁面載入流程(二)
上一篇講了Window的建立,但其顯示流程還沒有講清楚就跑路了
廢話不多說,我們continue
PS::blush::blush:英文用錯了場景別笑話,誰讓它是關鍵詞字:blush::blush:
WindowManager、WindowManagerImpl和WindowManagerGlobal的關係及內部機制
WindowManager是一個繼承於ViewManager的介面,實現類是WindowManagerImpl
Activity.java
final void attach(...){ ... mWindow.setWindowManager( (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),//系統的WindowManger mToken, mComponent.flattenToString(), (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0); ... mWindowManager = mWindow.getWindowManager(); }
Window.java
public void setWindowManager(WindowManager wm, IBinder appToken, String appName, boolean hardwareAccelerated) { ... //wm的createLocalWindowManager方法又重新new了WindowManagerImpl mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this); } public WindowManager getWindowManager() { return mWindowManager; }
WindowManagerImpl.java
WindowManagerImpl是WindowManager的實現類,顯實現了addView、updateViewLayout、removeView等方法,可是這哥們胸懷宇宙,有空還要看星星,別看它是一個實現類,名字還帶一個Impl,卻把具體工作都交給了單例的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, mContext.getDisplay(), 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); } ... }
WindowManagerGlobal.java
WindowManagerGlobal是單例的,所以它內部用幾個集合來儲存Window及引數和所對應的View
//每個Window對應的View private final ArrayList<View> mViews = new ArrayList<View>(); //每個Window對應的ViewRootImpl private final ArrayList<ViewRootImpl> mRoots = new ArrayList<ViewRootImpl>(); //每個Window的引數 private final ArrayList<WindowManager.LayoutParams> mParams = new ArrayList<WindowManager.LayoutParams>();
public void addView(View view, ViewGroup.LayoutParams params, Display display, Window parentWindow) { ViewRootImpl root; ... //建立ViewRootImpl,View的invalidate更新view的時候,就是從ViewRootImpl開始的 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); } ... }
Window的顯示
WindowManagerService作為一個系統級的服務執行在一個單獨的程序,所以WindowManager和它之間的互動是一個IPC(程序間通訊)過程,ViewRootImpl充當了橋樑的作為
通過Binder機制獲取WMS,在WindowManagerService獲取舒適化Session,進而通過session的addToDisplay方法和WMS的addWindow新增到將Window新增到裝置
ViewRootImpl.java
final IWindowSession mWindowSession; public ViewRootImpl(Context context, Display display) { ... //在構造方法裡呼叫WindowManagerGlobal的static方法getWindowSession()初始化IWindowSession mWindowSession = WindowManagerGlobal.getWindowSession(); ... } public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) { ... //開始View的三大流程,測量、佈局和繪製 requestLayout(); ... try { ... //顯示 res = mWindowSession.addToDisplay(mWindow,...); ... } ... }
WindowManagerGlobal.java
public static IWindowSession getWindowSession() { synchronized (WindowManagerGlobal.class) { if (sWindowSession == null) { try { InputMethodManager imm = InputMethodManager.getInstance(); IWindowManager windowManager = getWindowManagerService(); //從WindowManagerService裡獲取WindowSession sWindowSession = windowManager.openSession( new IWindowSessionCallback.Stub() { @Override public void onAnimatorScaleChanged(float scale) { ValueAnimator.setDurationScale(scale); } }, imm.getClient(), imm.getInputContext());ffgetWindowManagerService } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } return sWindowSession; } } public static IWindowManager getWindowManagerService() { synchronized (WindowManagerGlobal.class) { if (sWindowManagerService == null) { //從binder裡獲取WindowManagerService sWindowManagerService = IWindowManager.Stub.asInterface(ServiceManager.getService("window")); try { if (sWindowManagerService != null) { ValueAnimator.setDurationScale(sWindowManagerService.getCurrentAnimatorScale()); } } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } return sWindowManagerService; } }
WindowManagerService.java
@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和WindowManagerService相互持有 Session session = new Session(this, callback, client, inputContext); return session; }
Session.java
@Override public int addToDisplay(IWindow window, ...) { //這裡呼叫WMS的addWindow方法 return mService.addWindow(this, window, ...); }
Window已經顯示了
Activity的頁面載入流程已經結束,涉及到的類比較多,可能有說的不明的或錯誤的地方,請諒解
原始碼一個class動輒萬行,內部類N多個
是不是腦殼疼
疼就對了
不然你以為你zou是谷歌開發工程師了
然
不進則退
學習還是必須的
沒有什麼比自身的強大更重要
你想要的
時間都會給你
學會自我約束
才能自我自由
雞湯是給你們喝的,我喜歡吃肉