设为首页 加入收藏

TOP

源码分析:onAttach, onMeasure, onLayout, onDraw 的顺序。(一)
2015-07-24 05:57:12 来源: 作者: 【 】 浏览:40
Tags:源码 分析 onAttach onMeasure onLayout onDraw 顺序

从前文《 源码解析:dialog, popupwindow, 和activity 的第一个view是怎么来的?》中知道了activity第一个view或者说根view或者说mDecorView 其实就是一个FrameLayout,以及是在系统handleResume的时候加入到系统windowManager中的,并由framework中的ViewRootImpl 接管,通过ViewRootImpl.setView() 开始整个显示过程的。这次着重梳理一下view的显示过程(onAttach, onMeasure, onLayout, onDraw )在源码中的过程。

从ViewRootImpl.setview 开始。

    public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
        synchronized (this) {
            if (mView == null) {
                mView = view;

                requestLayout();
                if ((mWindowAttributes.inputFeatures
                        & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
                    mInputChannel = new InputChannel();
                }
                try {
                    mOrigWindowType = mWindowAttributes.type;
                    res = sWindowSession.add(mWindow, mSeq, mWindowAttributes,
                            getHostVisibility(), mAttachInfo.mContentInsets,
                            mInputChannel);
                } catch (RemoteException e) {
                    mAdded = false;
                    mView = null;
                    mAttachInfo.mRootView = null;
                    mInputChannel = null;
                    mFallbackEventHandler.setView(null);
                    unscheduleTraversals();
                    throw new RuntimeException("Adding window failed", e);
                } finally {
                    if (restore) {
                        attrs.restore();
                    }
                }
在第一次赋值mView的时候,会调用ViewRootImpl.requestLayout();

    public void requestLayout() {
        checkThread();
        mLayoutRequested = true;
        scheduleTraversals();
    }
进而scheduleTraversals();

    public void scheduleTraversals() {
        if (!mTraversalScheduled) {
            mTraversalScheduled = true;

            //noinspection ConstantConditions
            if (ViewDebug.DEBUG_LATENCY && mLastTraversalFinishedTimeNanos != 0) {
                final long now = System.nanoTime();
                Log.d(TAG, "Latency: Scheduled traversal, it has been "
                        + ((now - mLastTraversalFinishedTimeNanos) * 0.000001f)
                        + "ms since the last traversal finished.");
            }

            sendEmptyMessage(DO_TRAVERSAL);
        }
    }
进而在handleMessage() 中

    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
        case DO_TRAVERSAL:

            performTraversals();
	}
进而就是performTraversals(),也就是本次分析的重点。

这个函数比较长,不适合把全部函数代码都 贴上来。就分段叙述。

1. 函数刚开始的部分,初始化了一些后面会用到的变量和标志位。

        final View host = mView;
        WindowManager.LayoutParams lp = mWindowAttributes;
        final View.AttachInfo attachInfo = mAttachInfo;
        CompatibilityInfo compatibilityInfo = mCompatibilityInfo.get();
        Rect frame = mWinFrame;
        mTraversalScheduled = false;
        mWillDrawSoon = true;
        boolean windowSizeMayChange = false;
        boolean fullRedrawNeeded = mFullRedrawNeeded;
        boolean newSurface = false;
        boolean surfaceChanged = false;

2. 接下来,是一个重要的判断, 如果是初次执行,则调用host.dispatchAttachedToWindow(attachInfo, 0);

        if (mFirst) {
            // 略去一大堆赋值
            mLastConfiguration.setTo(host.getResources().getConfiguration());
            host.dispatchAttachedToWindow(attachInfo, 0);
            //Log.i(TAG, "Screen on initialized: " + attachInfo.mKeepScreenOn);

            host.fitSystemWindows(mAttachInfo.mContentInsets);

        } else {
            desiredWindowWidth = frame.width();
            desiredWindowHeight = frame.height();
            if (desiredWindowWidth != mWidth || desiredWindowHeight != mHeight) {
                if (DEBUG_ORIENTATION) Log.v(TAG,
                        "View " + host + " resized to: " + frame);
                fullRedrawNeeded = true;
                mLayoutRequested = true;
                windowSizeMayChange = true;
            }
        }
在dispatchAttachedToWindow()中重点处理了三件事:

2.1. onAttachedToWindow();

2.2. listener.onViewAttachedToWindow(this);

2.3 onWindowVisibilityChanged(vis);

    void dispatchAttachedToWindow(AttachInfo info, int visibility) {
        //System.out.println("Attached! " + t
首页 上一页 1 2 3 4 5 6 下一页 尾页 1/6/6
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇uva 11825 Hackers' Crackdow.. 下一篇解决TextView错位的问题

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: