DecorView:创建与显示

1、DecorView 创建
  1. 创建 PhoneWindow 对象。
  2. 为 PhoneWindow 设置 WindowManager 对象。
  3. 为 PhoneWindow 创建一个 DecorView 对象。
  4. 为 DecorView 的 ContentView 设置 activity 中设置的布局文件。
Activity.java
	
	    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) {
        attachBaseContext(context);

        mFragments.attachHost(null /*parent*/);
        
		// 1.初始化 Window 对象。
        mWindow = new PhoneWindow(this, window, activityConfigCallback);
        // 2.设置回调,向 Activity 分发事件。
        mWindow.setWindowControllerCallback(this);
        mWindow.setCallback(this);
        mWindow.setOnWindowDismissedCallback(this);
    	...
    	// 3.mWindow 设置 WindowManager 对象。
        mWindow.setWindowManager(
                (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
                mToken, mComponent.flattenToString(),
                (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
        if (mParent != null) {
            mWindow.setContainer(mParent.getWindow());
        }
        // 4.初始化 WindowManager 对象。
        mWindowManager = mWindow.getWindowManager();
    }
	
	// 设置 ContentView 布局
    public void setContentView(@LayoutRes int layoutResID) {
    	// 为 mWindow 设置布局
        getWindow().setContentView(layoutResID);
        initWindowDecorActionBar();
    }
PhoneWindow.java
	// mWindow 设置布局。
    @Override
    public void setContentView(int layoutResID) {
        // 1.mContentParent 为 null,创建一个 DecorView。
        if (mContentParent == null) {
            installDecor();
        } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
        	// 不为 null,移除其中所有 View。
            mContentParent.removeAllViews();
        }

        if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
            final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
                    getContext());
            transitionTo(newScene);
        } else {
        	// 2.为 mContentParent 添加布局。
            mLayoutInflater.inflate(layoutResID, mContentParent);
        }
        mContentParent.requestApplyInsets();
        final Callback cb = getCallback();
        if (cb != null && !isDestroyed()) {
        	// 3.回调通知,内容改变。
            cb.onContentChanged();
        }
        mContentParentExplicitlySet = true;
    }
    
	// 创建一个 DecorView
    private void installDecor() {
        mForceDecorInstall = false;
        if (mDecor == null) {
        	// 1.生成 DecorView。
            mDecor = generateDecor(-1);
            mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
            mDecor.setIsRootNamespace(true);
            if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
                mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
            }
        } else {
            mDecor.setWindow(this);
        }
        if (mContentParent == null) {
        	// 2.为 DecorView 设置 mContentParent 布局。
            mContentParent = generateLayout(mDecor);

            // Set up decor part of UI to ignore fitsSystemWindows if appropriate.
            mDecor.makeOptionalFitsSystemWindows();

            final DecorContentParent decorContentParent = (DecorContentParent) mDecor.findViewById(
                    R.id.decor_content_parent);
			。。。
    }

	// 生成 DecorView。
    protected DecorView generateDecor(int featureId) {
     	。。。
        return new DecorView(context, featureId, this, getAttributes());
    }

	// 生成 DecorView 的 mContentParent。
    protected ViewGroup generateLayout(DecorView decor) {
		
		// 1.获取 Window 主题信息。
        TypedArray a = getWindowStyle();
		。。。
        // Inflate the window decor.
		// 2. 根据主题样式,加载窗口布局。
        int layoutResource;
        int features = getLocalFeatures();
		。。。
		// 3.加载 layoutResource,往 DecorView 添加子 View。
        mDecor.onResourcesLoaded(mLayoutInflater, layoutResource);
		// 4.获取 DecorView 的内容布局 mContentParent 。
        ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
      	// ...设置 TitleView

        return contentParent;
    }
2、DecorView 显示
  1. 启动 Activity 后,主线程会调用 handleResumeActivity()。
  2. 将 DecorView 对象添加到 WindowManager。
  3. 创建 ViewRootImpl 对象。
  4. WindowManager 将 DecorView 交给 ViewRootImpl 对象。
  5. ViewRootImpl 通过 Handler 向主线程发送消息遍历绘制视图:performTraversals() 执行 View 的绘制流程。
ActivityThread.java

    final void handleResumeActivity(IBinder token,
            boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
      
        r = performResumeActivity(token, clearHide, reason);
        if (r != null) {
            final Activity a = r.activity;
			。。。
            if (r.window == null && !a.mFinished && willBeVisible) {
                r.window = r.activity.getWindow();
                // 1.获取 window 的 DecorView 对象。
                View decor = r.window.getDecorView();
                 // 2.DecorView 设置不可见。
                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) {
                    if (!a.mWindowAdded) {
                        a.mWindowAdded = true;
                        // 3.将 DecorView 添加到 WindowManager。
                        wm.addView(decor, l);
                    } else {
                        // The activity will get a callback for this {@link LayoutParams} change
                        // earlier. However, at that time the decor will not be set (this is set
                        // in this method), so no action will be taken. This call ensures the
                        // callback occurs with the decor set.
                        a.onWindowAttributesChanged(l);
                    }
                }

            // 4.设置 DecorView 可见。
            if (!r.activity.mFinished && willBeVisible
                    && r.activity.mDecor != null && !r.hideForNow) {
               。。。
                if (r.activity.mVisibleFromClient) {
                    r.activity.makeVisible();
                }
            }
 
            // Tell the activity manager we have resumed.
     
    }
Activity.java

    void makeVisible() {
        if (!mWindowAdded) {
            ViewManager wm = getWindowManager();
            // 1.将 DecorView 添加到 WindowManager。
            wm.addView(mDecor, getWindow().getAttributes());
            mWindowAdded = true;
        }
        // 2.设置 DecorView 可见。
        mDecor.setVisibility(View.VISIBLE);
    }
WindowManagerImpl.java

public final class WindowManagerImpl implements WindowManager {
    private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();

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

}
WindowManagerGlobal.java

public final class WindowManagerGlobal {

    public void addView(View view, ViewGroup.LayoutParams params,
            Display display, Window parentWindow) {
		。。。
        final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
       		 。。。
        	// 1.创建 ViewRootImpl 对象。
        	ViewRootImpl root;
            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 {
            	// 2.WindowManager 将 DecorView 对象交给 ViewRootImpl 绘制 View
                root.setView(view, wparams, panelParentView);
            } catch (RuntimeException e) {
                // BadTokenException or InvalidDisplayException, clean up.
                if (index >= 0) {
                    removeViewLocked(index, true);
                }
                throw e;
            }
        }
    }
    
}
ViewRootImpl.java

   public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
        synchronized (this) {
        requestLayout();
	}

    @Override
    public void requestLayout() {
        if (!mHandlingLayoutInLayoutRequest) {
        	// 1.检查是否在主线程。
            checkThread();
            // mLayoutRequested 表示是否 measure 和 layout 布局。
            mLayoutRequested = true;
            scheduleTraversals();
        }
    }
    
    void scheduleTraversals() {
        if (!mTraversalScheduled) {
            mTraversalScheduled = true;
            mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
            // 1.类似 Handler.post() 方法,mTraversalRunnable 处理绘制流程。
            mChoreographer.postCallback(
                    Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
            if (!mUnbufferedInputDispatch) {
                scheduleConsumeBatchedInput();
            }
            notifyRendererOfFramePending();
            pokeDrawLockIfNeeded();
        }
    }
    
    final class TraversalRunnable implements Runnable {
        @Override
        public void run() {
            doTraversal();
        }
    }
    final TraversalRunnable mTraversalRunnable = new TraversalRunnable();

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

            if (mProfile) {
                Debug.startMethodTracing("ViewAncestor");
            }
			// 1.开始 View 的3大流程:Measure、Layout、Draw。
            performTraversals();

            if (mProfile) {
                Debug.stopMethodTracing();
                mProfile = false;
            }
        }
    }
    
    // W 类为 Binder 的 Native 端。用于接收 WMS 处理操作;W 类接收的方法是在线程池中,可以通过 Handler 将事件处理切换到主线程中。
   static class W extends IWindow.Stub {
   }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值