View的绘制流程分析之二-Android对Window对象的管理机制分析

关于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);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

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

这里写图片描述


addView

 @Override
    public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
        applyDefaultToken(params);
        mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
  • 1
  • 2
  • 3
  • 4
  • 5

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

在WindowManagerImpl类中进行了初始化

private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
  • 1

WindowManagerGlobal.java

private WindowManagerGlobal() {
    }

    public static WindowManagerGlobal getInstance() {
        synchronized (WindowManagerGlobal.class) {
            if (sDefaultWindowManager == null) {
                sDefaultWindowManager = new WindowManagerGlobal();
            }
            return sDefaultWindowManager;
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

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


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>();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

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;
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70

函数最后通过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();
                    }
                }

            // ...
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

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);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

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


updateViewLayout

WindowMangerImpl.java

@Override
    public void updateViewLayout(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
        applyDefaultToken(params);
        mGlobal.updateViewLayout(view, params);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
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
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

ViewRooImpl.java

void setLayoutParams(WindowManager.LayoutParams attrs, boolean newView) {
        synchronized (this) {
            // ...

            if (newView) {
                mSoftInputMode = attrs.softInputMode;
                requestLayout();
            }

            //...

            mWindowAttributesChanged = true;
            scheduleTraversals();
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

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


removeView

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

public void removeView(View view);
  • 1

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

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

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

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

WindowManagerImpl.java

@Override
    public void removeView(View view) {
        mGlobal.removeView(view, false);
    }
  • 1
  • 2
  • 3
  • 4
@Override
    public void removeViewImmediate(View view) {
        mGlobal.removeView(view, true);
    }
  • 1
  • 2
  • 3
  • 4

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);
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

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);
            }
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

ViewRootImpl.java

boolean die(boolean immediate) {
        // 立刻删除时,直接执行doDie()函数完成真正的删除操作!然后返回false
        if (immediate && !mIsInTraversal) {
            doDie();
            return false;
        }

        // ...
        // 异步删除时,发送一个请求删除的消息,然后直接返回true
        mHandler.sendEmptyMessage(MSG_DIE);
        return true;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

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

case MSG_DIE:
   doDie();
   break;
  • 1
  • 2
  • 3

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);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

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();
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

再来看看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();
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

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

Session.java

public void remove(IWindow window) {
        mService.removeWindow(this, window);
    }
  • 1
  • 2
  • 3

WMS.java

public void removeWindow(Session session, IWindow client) {
        synchronized(mWindowMap) {
            WindowState win = windowForClientLocked(session, client, false);
            if (win == null) {
                return;
            }
            removeWindowLocked(win);
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
void removeWindowLocked(WindowState win) {
        removeWindowLocked(win, false);
    }
  • 1
  • 2
  • 3
void removeWindowLocked(WindowState win, boolean keepVisibleDeadWindow) {
        win.mWindowRemovalAllowed = true;
        // ...

        boolean wasVisible = false;
        // ...

        removeWindowInnerLocked(win);
        // ...
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

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

http://blog.csdn.net/crazy1235/article/details/72633389

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值