美文网首页
View工作原理

View工作原理

作者: 紫苓 | 来源:发表于2016-08-18 20:02 被阅读101次

    1、起步分析

    Activity启动分析中 知道,Activity的创建是在ActivityThread.performLaunchActivity()中进行的,然后依次执行了Activity.attach()、Activity.onCreate()、Activity.onStart()、Activity.OnRestoreInstanceState()等生命周期方法之后,回到ActivityThread.handleLaunchActivity()中继续执行ActivityThread.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
            // 执行onResume()生命周期函数
            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 ?
                        WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION : 0;
    
                // If the window hasn't yet been added to the window manager,
                // and this guy didn't finish itself or start another activity,
                // then go ahead and add the window.
                // Activity现在还不可见,willBeVisible = true
                boolean willBeVisible = !a.mStartedActivity;
                if (!willBeVisible) {
                    try {
                        willBeVisible = ActivityManagerNative.getDefault().willActivityBeVisible(
                                a.getActivityToken());
                    } catch (RemoteException e) {
                    }
                }
                // Activity第一次启动,把DecorView加入到Window
                if (r.window == null && !a.mFinished && willBeVisible) {
                    // activity持有的window对象赋值给ActivityClientRecord
                    r.window = r.activity.getWindow();
                    // DecorView
                    View decor = r.window.getDecorView();
                    // 设置DecorView不可见
                    decor.setVisibility(View.INVISIBLE);
                    // ViewManager是用来为Activity添加或是移除子View的接口
                    // 要获取该类的实例可以通过Context.getSystemService()
                    // WindowManager实现了ViewManager,
                    // Activity.getWindowManager()返回的是一个WindowManager对象
                    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;
                        // 把DecorView加入到Activity中
                        wm.addView(decor, l);
                    }
    
                // If the window has already been added, but during resume
                // we started another activity, then don't yet make the
                // window visible.
                } else if (!willBeVisible) {
                    if (localLOGV) Slog.v(
                        TAG, "Launch " + r + " mStartedActivity set");
                    r.hideForNow = true;
                }
                // ......
        }
    

    在该方法中,DecorView通过ViewManager.addView()方法被加入到了Activity中,至于DecorView是什么,可以看看View事件分发机制,里面有相关的描述。
    WindowManagerImpl.addView()

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

    WindowManagerGlobal.addView()

    public void addView(View view, ViewGroup.LayoutParams params,
                Display display, Window parentWindow) {
            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 {
                // If there's no parent, then hardware acceleration for this view is
                // set from the application's hardware acceleration setting.
                // 硬件加速设置
                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;
            View panelParentView = null;
    
            synchronized (mLock) {
                // Start watching for system property changes.
                if (mSystemPropertyUpdater == null) {
                    mSystemPropertyUpdater = new Runnable() {
                        @Override public void run() {
                            synchronized (mLock) {
                                for (int i = mRoots.size() - 1; i >= 0; --i) {
                                    mRoots.get(i).loadSystemProperties();
                                }
                            }
                        }
                    };
                    SystemProperties.addChangeCallback(mSystemPropertyUpdater);
                }
    
                int index = findViewLocked(view, false);
                if (index >= 0) {
                    // 该decorView已经存在了,移除掉
                    if (mDyingViews.contains(view)) {
                        // Don't wait for MSG_DIE to make it's way through root's queue.
                        mRoots.get(index).doDie();
                    } else {
                        throw new IllegalStateException("View " + view
                                + " has already been added to the window manager.");
                    }
                    // The previous removeView() had not completed executing. Now it has.
                }
    
                // If this is a panel window, then find the window it is being
                // attached to for future reference.
                if (wparams.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW &&
                        wparams.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
                    final int count = mViews.size();
                    for (int i = 0; i < count; i++) {
                        if (mRoots.get(i).mWindow.asBinder() == wparams.token) {
                            panelParentView = mViews.get(i);
                        }
                    }
                }
                // 创建ViewParent
                root = new ViewRootImpl(view.getContext(), display);
                // 给DecorView添加布局参数
                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.
                synchronized (mLock) {
                    final int index = findViewLocked(view, false);
                    if (index >= 0) {
                        removeViewLocked(index, true);
                    }
                }
                throw e;
            }
        }
    

    ViewRootImpl.setView()

        public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
            //.......
            requestLayout();
            //......
        }
    
    @Override
        public void requestLayout() {
            if (!mHandlingLayoutInLayoutRequest) {
                // 检查运行线程是否为UI线程,如果不是的话,抛出一个非常熟悉的异常信息
                checkThread();
                mLayoutRequested = true;
                //
                scheduleTraversals();
            }
        }
    
    void scheduleTraversals() {
            if (!mTraversalScheduled) {
                mTraversalScheduled = true;
                mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
                mChoreographer.postCallback(
                        Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
               //......
            }
        }
    
    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显示相关工作
                performTraversals();
    
                if (mProfile) {
                    Debug.stopMethodTracing();
                    mProfile = false;
                }
            }
        }
    

    以上,就是Activity 在onResume之后对View的预处理过程:从Activity中获取到WindowManager和DecorView,从Window中获取到WindowManager.LayoutParams布局参数,然后通过WindowManager.addView()(最终是通过ViewParent)把DecorView添加到窗口中。

    2、View工作原理

    相关文章

      网友评论

          本文标题:View工作原理

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