Android对Window对象的管理机制分析

来源:互联网 发布:pmp含金量 知乎 编辑:程序博客网 时间:2024/06/03 23:43

转载请注明出处:http://blog.csdn.net/crazy1235/article/details/72625679


关于Window对象管理的相关类:


  • ViewManager

  • WindowManager

  • WindowManagerImpl

  • WindowManagerGlobal

  • ViewParent

  • ViewRootImpl

  • ActvityThread

  • WindowManagerService


Window是一个抽象类,具体实现类就是 PhoneWindow

一个Window是通过一个View来承载的,还对应一个ViewRootImpl!

访问Window必须通过WindowManager来实现!

Window具体操作方法实现实在WindowManagerImpl类中,方法定义在ViewManager接口中!

public interface ViewManager{        public void addView(View view, ViewGroup.LayoutParams params);    public void updateViewLayout(View view, ViewGroup.LayoutParams params);    public void removeView(View view);}

ViewManager接口定义了三个函数,分别对应window的添加,更新和删除!

这里写图片描述


addView

 @Override    public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {        applyDefaultToken(params);        mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);

其实WindowManagerImpl也没有做具体的操作,而是交给了 WindowManagerGlobal

在WindowManagerImpl类中进行了初始化

private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();

WindowManagerGlobal.java

private WindowManagerGlobal() {    }    public static WindowManagerGlobal getInstance() {        synchronized (WindowManagerGlobal.class) {            if (sDefaultWindowManager == null) {                sDefaultWindowManager = new WindowManagerGlobal();            }            return sDefaultWindowManager;        }    }

很明显看出这是个单例模式


private final ArrayList<View> mViews = new ArrayList<View>();private final ArrayList<ViewRootImpl> mRoots = new ArrayList<ViewRootImpl>();private final ArrayList<WindowManager.LayoutParams> mParams =            new ArrayList<WindowManager.LayoutParams>();private final ArraySet<View> mDyingViews = new ArraySet<View>();

WindowManagerGlobal中有四个重要的集合!

  • mViews集合存储了所有window对应的View对象!

  • mRoots集合存储了所有window对应的ViewRootImpl对象

  • mParams集合存储了所有window对应的布局参数

  • mDyingViews集合存储了所有正在被删除的window对象


public void addView(View view, ViewGroup.LayoutParams params,            Display display, Window parentWindow) {        // 1. 验证参数!        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 {            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; // 一个ViewRootImpl对象        View panelParentView = null; // 一个View对象        synchronized (mLock) {            // ...            // 查找view对应的index            int index = findViewLocked(view, false);            if (index >= 0) {                if (mDyingViews.contains(view)) {// 如果正在被删除的集合包含该view,则执行ViewRootImpl.doDie()函数                    mRoots.get(index).doDie();                } else {                    throw new IllegalStateException("View " + view                            + " has already been added to the window manager.");                }           }            // ...             // 创建ViewRootImpl对象            root = new ViewRootImpl(view.getContext(), display);            // 设置布局参数            view.setLayoutParams(wparams);            // 添加view到集合中            mViews.add(view);            // 添加ViewRootImpl到集合中            mRoots.add(root);            // 添加wparams参数到集合中            mParams.add(wparams);        }        try {            // 将view设置到ViewRootImpl中!            root.setView(view, wparams, panelParentView);        } catch (RuntimeException e) {            // 设置异常则移除view            synchronized (mLock) {                final int index = findViewLocked(view, false);                if (index >= 0) {                    removeViewLocked(index, true);                }            }            throw e;        }    }

函数最后通过ViewRootImpl.setView() 来完成window的添加过程!

在setView()内部调用了requestLayout()开启了绘制流程!

View的绘制流程是由ViewRootImpl来完成的!

requestLayout(); 完成绘制流程之后,通过WindowSession来完成Window的添加过程!

public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {            // ...            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);                    throw new RuntimeException("Adding window failed", e);                } finally {                    if (restore) {                        attrs.restore();                    }                }            // ...}

mWindowSession是IWindowSession类型变量,它是一个Binder对象!

真正的实现者是 Session

@Override    public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,            int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets,            Rect outOutsets, InputChannel outInputChannel) {        return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId,                outContentInsets, outStableInsets, outOutsets, outInputChannel);    }

这里又通过WindowManagerService来实现window的添加,这样window的添加事务就交给了WMS进行处理!


updateViewLayout

WindowMangerImpl.java

@Override    public void updateViewLayout(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {        applyDefaultToken(params);        mGlobal.updateViewLayout(view, params);    }
public void updateViewLayout(View view, ViewGroup.LayoutParams params) {        // ...        final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams)params;        // 设置新的布局参数        view.setLayoutParams(wparams);         synchronized (mLock) {            int index = findViewLocked(view, true);            ViewRootImpl root = mRoots.get(index);            mParams.remove(index);            mParams.add(index, wparams); // 更新mParams集合对应的值            root.setLayoutParams(wparams, false); // 更新ViewRootImpl中的参数, false表示不是一个新的view        }    }

ViewRooImpl.java

void setLayoutParams(WindowManager.LayoutParams attrs, boolean newView) {        synchronized (this) {            // ...            if (newView) {                mSoftInputMode = attrs.softInputMode;                requestLayout();            }            //...            mWindowAttributesChanged = true;            scheduleTraversals();        }    }

在这个函数里面又调用了scheduleTraversals() 来重新进行测量,布局,绘制流程!


removeView

在ViewManager接口中只有一种删除函数:

public void removeView(View view);

但是在WindowManager接口中又增加了一种删除view的方式:

public void removeViewImmediate(View view); // 立即删除

这两种方式,一种表示同步删除,一种表示异步删除

但是两者都会去调用 WindowManagerGlobal中的 removeView() 函数!

WindowManagerImpl.java

@Override    public void removeView(View view) {        mGlobal.removeView(view, false);    }
@Override    public void removeViewImmediate(View view) {        mGlobal.removeView(view, true);    }

WindowManagerGlobal.java

public void removeView(View view, boolean immediate) {        if (view == null) {            throw new IllegalArgumentException("view must not be null");        }        synchronized (mLock) {            // 查找要被删除view的索引            int index = findViewLocked(view, true);            // 从mRoots这个集合中得到view对象            View curView = mRoots.get(index).getView();            // 执行删除操作            removeViewLocked(index, immediate);            if (curView == view) {                return;            }            throw new IllegalStateException("Calling with view " + view                    + " but the ViewAncestor is attached to " + curView);        }    }

removeView() 第二个参数表示是否立刻删除~

private void removeViewLocked(int index, boolean immediate) {        // 获取view对应的ViewRootImpl对象        ViewRootImpl root = mRoots.get(index);        View view = root.getView();        // ...        // 调用View中的die()函数        boolean deferred = root.die(immediate);        if (view != null) {            view.assignParent(null);            if (deferred) { // 添加到正在被删除的集合中                mDyingViews.add(view);            }        }    }

ViewRootImpl.java

boolean die(boolean immediate) {        // 立刻删除时,直接执行doDie()函数完成真正的删除操作!然后返回false        if (immediate && !mIsInTraversal) {            doDie();            return false;        }        // ...        // 异步删除时,发送一个请求删除的消息,然后直接返回true        mHandler.sendEmptyMessage(MSG_DIE);        return true;    }

其实在异步删除时,handler处理的时候也是调用的doDie()函数来完成删除!

case MSG_DIE:   doDie();   break;

ViewRootImpl.java

void doDie() {        checkThread(); // 检查线程, 很多地方都会调用这个函数!        synchronized (this) {            if (mRemoved) { // mRemoved默认是false,doDie()函数执行时变为true                return;            }            mRemoved = true;            if (mAdded) { // 如果当前window对象应被添加到屏幕上!则需要回调detach函数                dispatchDetachedFromWindow();            }            if (mAdded && !mFirst) {                destroyHardwareRenderer(); // 停止硬件渲染                if (mView != null) {                    int viewVisibility = mView.getVisibility();                    boolean viewVisibilityChanged = mViewVisibility != viewVisibility;                    if (mWindowAttributesChanged || viewVisibilityChanged) { // 如果window属性更改或者显示方式改变                        try {                            if ((relayoutWindow(mWindowAttributes, viewVisibility, false)                                    & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {                                mWindowSession.finishDrawing(mWindow);                            }                        } catch (RemoteException e) {                        }                    }                    mSurface.release(); // 释放资源                }            }            mAdded = false; // 状态还原        }        WindowManagerGlobal.getInstance().doRemoveView(this);    }

WindowManagerGlobal.java

void doRemoveView(ViewRootImpl root) {        synchronized (mLock) {            final int index = mRoots.indexOf(root);             if (index >= 0) {                mRoots.remove(index);// 从ViewRootImpl集合中删除                mParams.remove(index); //  删除对应的参数                final View view = mViews.remove(index); // 删除对应的view                mDyingViews.remove(view);// 从正在被删除的集合中删除view            }        }        if (ThreadedRenderer.sTrimForeground && ThreadedRenderer.isAvailable()) {            doTrimForeground();        }    }

再来看看dispatchDetachedFromWindow()函数

void dispatchDetachedFromWindow() {        if (mView != null && mView.mAttachInfo != null) {            mAttachInfo.mTreeObserver.dispatchOnWindowAttachedChange(false);            mView.dispatchDetachedFromWindow(); // 回调view的detach函数!方法内部会调用onDetachedFromWidow()函数 和 onDetachedFromWindowInternal()函数        }        // ...        destroyHardwareRenderer();        // ...        mSurface.release();        // ...        try {            mWindowSession.remove(mWindow);        } catch (RemoteException e) {        }        // ...        mDisplayManager.unregisterDisplayListener(mDisplayListener);        unscheduleTraversals();    }

再次通过IPC方式调用remove()函数!

Session.java

public void remove(IWindow window) {        mService.removeWindow(this, window);    }

WMS.java

public void removeWindow(Session session, IWindow client) {        synchronized(mWindowMap) {            WindowState win = windowForClientLocked(session, client, false);            if (win == null) {                return;            }            removeWindowLocked(win);        }    }
void removeWindowLocked(WindowState win) {        removeWindowLocked(win, false);    }
void removeWindowLocked(WindowState win, boolean keepVisibleDeadWindow) {        win.mWindowRemovalAllowed = true;        // ...        boolean wasVisible = false;        // ...        removeWindowInnerLocked(win);        // ...    }

removeWindowInnerLocked(win); 方法内部分析先暂停!!!

阅读全文
1 0