美文网首页
2018-12-18view 绘制流程

2018-12-18view 绘制流程

作者: 猫KK | 来源:发表于2018-12-18 22:56 被阅读0次

本章主要介绍view 绘制流程中什么时候初始化ViewRootImpl,什么时候调用performTraversals()方法

初始化

根据Activity 的跳转我们知道最后会调用 ActicityTheard 中的 handleLaunchActivity方法,来看看这个方法
注:我看的是6.0的源码,9.0的源码和6.0的源码有很大的改变,暂时不看


    private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        //省略部分代码
        //该方法创建Activity 实例并调用Activity 的onCreate、onStart方法
        Activity a = performLaunchActivity(r, customIntent);

        if (a != null) {
            r.createdConfig = new Configuration(mConfiguration);
            Bundle oldState = r.state;
            //最后走到这
            handleResumeActivity(r.token, false, r.isForward,
                    !r.activity.mFinished && !r.startsNotResumed);

           //省略部分代码
    }

再来看 handleResumeActivity 方法

final void handleResumeActivity(IBinder token,
            boolean clearHide, boolean isForward, boolean reallyResume) {
        // If we are getting ready to gc after going to the background, well
        // we are back active so skip it.
        unscheduleGcIdler();
        mSomeActivitiesChanged = true;

        // TODO Push resumeArgs into the activity for consideration
        //这里就会调用Acticity 的Resume 方法
        ActivityClientRecord r = performResumeActivity(token, clearHide);

        if (r != null) {
            final Activity a = r.activity;

            if (localLOGV) Slog.v(
                TAG, "Resume " + r + " started activity: " +
                a.mStartedActivity + ", hideForNow: " + r.hideForNow
                + ", finished: " + a.mFinished);

            final int forwardBit = isForward ?
           //...........
            if (r.window == null && !a.mFinished && willBeVisible) {
                r.window = r.activity.getWindow();
                View decor = r.window.getDecorView();
                decor.setVisibility(View.INVISIBLE);
                ViewManager wm = a.getWindowManager();
                WindowManager.LayoutParams l = r.window.getAttributes();
                a.mDecor = decor;
                l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
                l.softInputMode |= forwardBit;
                if (a.mVisibleFromClient) {
                    a.mWindowAdded = true;
                    //我们主要来看这一句,ViewManager 是一个接口,看它的实例对象
                    wm.addView(decor, l);
                }
        }
  //............
    }

通过上面知道调用了 ViewManager.addView,ViewManager是一个接口对象,我们要找到对应的实例对象

//Acticity 中
 /** Retrieve the window manager for showing custom windows. */
    public WindowManager getWindowManager() {
        return mWindowManager;
    }

final void attach(Context context, ActivityThread aThread,
            Instrumentation instr, IBinder token, int ident,
            Application application, Intent intent, ActivityInfo info,
            CharSequence title, Activity parent, String id,
            NonConfigurationInstances lastNonConfigurationInstances,
            Configuration config, String referrer, IVoiceInteractor voiceInteractor,
            Window window, ActivityConfigCallback activityConfigCallback) {
         ......
        //为 mWindow 设置 WindowManager
        mWindow.setWindowManager(
                (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
                mToken, mComponent.flattenToString(),
                (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
        //通过 mWindow 获取
        mWindowManager = mWindow.getWindowManager();
        .......
    }

通过上面可以知道,先通过 mWindow 设置一个 WindowManager 然后在通过 mWindow 获取一个 WindowManager,来看 mWindow.setWindowManager 做了什么

    public void setWindowManager(WindowManager wm, IBinder appToken, String appName,
            boolean hardwareAccelerated) {
        //通过 WindowManager 创建一个实现类 WindowManagerImpl
        mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
    }
    
    //getWindowManager 就是返回上面创建的实现类,所以 mWindowManager 就是
    public WindowManager getWindowManager() {
        return mWindowManager;
    }

通过上面可以知道 WindowManager 的实现类就是 WindowManagerImpl,所以wm.addView(decor, l); 就是WindowManagerImpl.addView()方法

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

继续跟进来到WindowManagerGlobal中


    public void addView(View view, ViewGroup.LayoutParams params,
            Display display, Window parentWindow) {
        // 到这里,才开始实例话ViewRootImpl 对象
        ViewRootImpl root;
        View panelParentView = null;
        //..........
        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);
            } catch (RuntimeException e) {
                // BadTokenException or InvalidDisplayException, clean up.
                if (index >= 0) {
                    removeViewLocked(index, true);
                }
                throw e;
            }
        }
    }

/**
     * We have one child
     */
    public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
                //........
                //来了,关键的方法,走了一路就是为了这个方法
                requestLayout();
                //.......
    }

来仔细看看 requestLayout();


    @Override
    public void requestLayout() {
        if (!mHandlingLayoutInLayoutRequest) {
            //检查线程,子线程更新UI会抛异常就是在这里
            checkThread();
            mLayoutRequested = true;
            //来看这个
            scheduleTraversals();
        }
    }


    void scheduleTraversals() {
        if (!mTraversalScheduled) {
            mTraversalScheduled = true;
            //设置Handler同步屏障,优先处理view绘制流程
            mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
          //主要是这一句,mChoreographer 就是Handler 的封装 我们来看mTraversalRunnable
            mChoreographer.postCallback(
                    Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
            if (!mUnbufferedInputDispatch) {
                scheduleConsumeBatchedInput();
            }
            notifyRendererOfFramePending();
            pokeDrawLockIfNeeded();
        }
    }

final class TraversalRunnable implements Runnable {
        @Override
        public void run() {
            doTraversal();
        }
    }

void doTraversal() {
        if (mTraversalScheduled) {
            mTraversalScheduled = false;
            mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);

            if (mProfile) {
                Debug.startMethodTracing("ViewAncestor");
            }

            //终于来了,view绘制流程开始的地方,这个方法就会调用view 的measure、layout、draw 方法
            performTraversals();

            if (mProfile) {
                Debug.stopMethodTracing();
                mProfile = false;
            }
        }
    }

经过上面的分析,我们知道ViewRootImpl 是在Resume 方法之后才实例的,所以在onResume 方法中还是不能获取到控件的实际宽高,需要调用 measure 方法后才能得到控件的实际宽高,performTraversals(); 方法下回在分析

相关文章

网友评论

      本文标题:2018-12-18view 绘制流程

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