美文网首页
Android Canvas的由来

Android Canvas的由来

作者: android_coder | 来源:发表于2020-10-15 15:20 被阅读0次
    1:前言

    在绘制过程中首先得了解几个比较重要的概念
    Window的类型和级别
    Surface是干什么的
    View中的ondraw方法里的Canvas对象是哪来的?
    WMS添加Window的过程,和事件传递机制

    2:Surface

    其实可以把它理解成是真正的画布,我们应用绘制View用的Canvas就是通过Surface来创建的,每一个Window中都存在一个自己的Surface,这个声明在ViewRootImpl中,但是ViewRootImpl中声明的Surface只是一个空壳,在绘制之前会调用relayoutWindow到WMS中去真正的创建Surface,它需要通过系统的SurfaceFlinger来整合显示,简单说就是Window需要通过Surface创建的Canvas来绘制要显示的内容,然后系统底层来控制Surface的整合展示,我们看来看一下Surface真正的创建过程和Canvas是怎么得来的

    2.1:ViewRootImpl之Surface申明
    ViewRootImpl中声明的Surface
    final Surface mSurface = new Surface();
    
    2.2:ViewRootImpl::performTraversals

    在ViewRootImpl的绘制方法中,也就是performTraversals中会在执行performDraw之前先去WMS端获取到native层Sureface

        private void performTraversals() {
            //顶层的View,可以理解成是DecorView
            final View host = mView;
           ...
            //通知被添加到窗口了,传入了mAttachInfo
            host.dispatchAttachedToWindow(mAttachInfo, 0);
             //调用relayoutWindow方法去获取native层的Surface
            relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);
            ...
            //measure过程
            performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
            ....
            //layout过程
            performLayout(lp, desiredWindowWidth, desiredWindowHeight);
            ....
            //通知layout完成了
            mAttachInfo.mTreeObserver.dispatchOnGlobalLayout();
            ....
            //draw过程
            performDraw();
        }
    
    2.3:relayoutWindow
    ViewRootImpl的relayoutWindow方法,去获取native行Surface
    private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility,
                boolean insetsPending) throws RemoteException {
        ....
            //调用了mWindowSession的relayout方法,上面我们知道IWindowSession真正实现是Session
            int relayoutResult = mWindowSession.relayout(
                    mWindow, mSeq, params,
                    (int) (mView.getMeasuredWidth() * appScale + 0.5f),
                    (int) (mView.getMeasuredHeight() * appScale + 0.5f),
                    viewVisibility, insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0,
                    mWinFrame, mPendingOverscanInsets, mPendingContentInsets, mPendingVisibleInsets,
                    mPendingStableInsets, mPendingOutsets, mPendingBackDropFrame, mPendingConfiguration,
                    mSurface);//最后一个参数传入了ViewRootImpl中的空壳Sureface
        ....
            return relayoutResult;
        }
    
    2.4:relayoutWindow
    Session中的relayoutWindow
        public int relayout(IWindow window, int seq, WindowManager.LayoutParams attrs,
                int requestedWidth, int requestedHeight, int viewFlags,
                int flags, Rect outFrame, Rect outOverscanInsets, Rect outContentInsets,
                Rect outVisibleInsets, Rect outStableInsets, Rect outsets, Rect outBackdropFrame,
                Configuration outConfig, Surface outSurface) {
            //直接调用了WMS的relayoutWIndow
            int res = mService.relayoutWindow(this, window, seq, attrs,
                    requestedWidth, requestedHeight, viewFlags, flags,
                    outFrame, outOverscanInsets, outContentInsets, outVisibleInsets,
                    outStableInsets, outsets, outBackdropFrame, outConfig, outSurface);
            return res;
        }
    
    2.5:relayoutWindow
    WindowManagerService中的relayoutWindow方法
        public int relayoutWindow(Session session, IWindow client, int seq,
                WindowManager.LayoutParams attrs, int requestedWidth,
                int requestedHeight, int viewVisibility, int flags,
                Rect outFrame, Rect outOverscanInsets, Rect outContentInsets,
                Rect outVisibleInsets, Rect outStableInsets, Rect outOutsets, Rect outBackdropFrame,
                Configuration outConfig, Surface outSurface) {
            ....
             //创建SurfaceControl并获取native中创建Surface
             result = createSurfaceControl(outSurface, result, win, winAnimator);
            ....
        }
    
    2.6:createSurfaceControl
    WindowManagerService中的createSurfaceControl方法
        private int createSurfaceControl(Surface outSurface, int result, WindowState win,
                WindowStateAnimator winAnimator) {
            if (!win.mHasSurface) {
                result |= RELAYOUT_RES_SURFACE_CHANGED;
            }
            WindowSurfaceController surfaceController = winAnimator.createSurfaceLocked();
            if (surfaceController != null) {
                //获取native层的Surface
                surfaceController.getSurface(outSurface);
            } else {
                outSurface.release();
            }
            return result;
        }
    
    2.7:getSurface
    WindowSurfaceController中的getSurface方法 
        void getSurface(Surface outSurface) {
            //调用了Surface中的copyFrom方法,从方法名体现的是将native层的Surface复制到客户端的空壳中
            outSurface.copyFrom(mSurfaceControl);
        }
    
    3:Canvas的创建
       在调用draw之前会先创建Canvas对象
        private boolean drawSoftware(Surface surface, AttachInfo attachInfo, int xoff, int yoff,
                boolean scalingRequired, Rect dirty) {
             final Canvas canvas;
            try {   
                //使用Surface创建一个Canvas,方法中也是调用了native方法    
                anvas = mSurface.lockCanvas(dirty);
                if (left != dirty.left || top != dirty.top || right != dirty.right
                        || bottom != dirty.bottom) {
                    attachInfo.mIgnoreDirtyState = true;
                }
                canvas.setDensity(mDensity);
            }catch (Surface.OutOfResourcesException e) {
                handleOutOfResourcesException(e);
                return false;
            } catch (IllegalArgumentException e) {
                mLayoutRequested = true;    // ask wm for a new surface next time.
                return false;
            }
            ....
              try {
                    canvas.translate(-xoff, -yoff);
                    if (mTranslator != null) {
                        mTranslator.translateCanvas(canvas);
                    }
                    canvas.setScreenDensity(scalingRequired ? mNoncompatDensity : 0);
                    attachInfo.mSetIgnoreDirtyState = false;
                    //调用View的draw方法,并传入刚刚创建的Canvas对象
                    mView.draw(canvas);
                    drawAccessibilityFocusedDrawableIfNeeded(canvas);
                } finally {
                    if (!attachInfo.mSetIgnoreDirtyState) {
                        // Only clear the flag if it was not set during the mView.draw() call
                        attachInfo.mIgnoreDirtyState = false;
                    }
                }
            ....
        }
    

    相关文章

      网友评论

          本文标题:Android Canvas的由来

          本文链接:https://www.haomeiwen.com/subject/waxopktx.html