AndroidのViewシステム(B):DecorViewの作成と表示

DecorViewは、一般的には垂直方向のLinearLayout内に、含ま垂直部が2のLinearLayoutに、タイトルバーの上に、次のコンテンツの列で、平面図です。私たちはsetContentViewによって設定されたレイアウトファイル内の活動は、実際にコンテンツフィールドにロードされます。

この記事では、作成する方法について説明しますとDecorViewが表示されます。

定義:本明細書において他に指定がない限り、api21の対応するソースコード解析。

.DecorViewを作成します。

我々はDecorViewからビューを描画を開始する準備ができて、その後、DecorViewはトップビュー表示で、前述しました。スタートDecorViewはおなじみのsetContentView()です。

   //代码片1 (Activity类)
   public void setContentView(int layoutResID) {
        getWindow().setContentView(layoutResID);
        initWindowDecorActionBar();
    }

発見の審査後、は、GetWindow()はWindowクラスを返します。そして、私たちが知っている、ウィンドウは抽象クラスですが、それだけでPhoneWindow実装クラスです。言い換えれば、は、GetWindow()。SetContentView(layoutResID)を知りたい、実際には、それはsetContentViewメソッドPhoneWindowクラスです。

//代码片2(PhoneWindow类)
@Override
    public void setContentView(int layoutResID) {
        // 1. 若mContentParent为空,创建一个DecroView
  		// mContentParent即为内容栏(content)对应的DecorView = FrameLayout子类
        if (mContentParent == null) {
            installDecor();      ---->分析1
        } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
            // 若不为空,则删除其中的View
            mContentParent.removeAllViews();
        }

        if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
            final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
                    getContext());
            transitionTo(newScene);
        } else {
            // 2. 为mContentParent添加子View
           // 即Activity中设置的布局文件
            mLayoutInflater.inflate(layoutResID, mContentParent);
        }
        final Callback cb = getCallback();
        if (cb != null && !isDestroyed()) {
            cb.onContentChanged();
        }
    }

我々は、コード板で2つの分析の部分(即ち、7行)を見て:

//代码片3(PhoneWindow类)
 private void installDecor() {
        if (mDecor == null) {
            //1. 通过赋值可以发现,mDecor就是DecorView。
            //  (DecorView的描述)This is the top-level view of the window, containing the window decor. 
            //  private DecorView mDecor;
            mDecor = generateDecor();   
            mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
            mDecor.setIsRootNamespace(true);
            if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
                mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
            }
        }
        if (mContentParent == null) {
            // 2.为DecorView设置布局格式 & 返回mContentParent ->>分析2
            mContentParent = generateLayout(mDecor);
//省略其他代码

シート3のコード解析部2で見てみましょう(すなわち、コードの第16行)。

//代码片4(PhoneWindow类)
**
  * 分析2generateLayout(mDecor)
  * 作用:为DecorView设置布局格式
  */
  protected ViewGroup generateLayout(DecorView decor) {

        // 1. 从主题文件中获取样式信息
        TypedArray a = getWindowStyle();

        // 2. 根据主题样式,加载窗口布局
        int layoutResource;
        int features = getLocalFeatures();

        // 3. 加载layoutResource
        View in = mLayoutInflater.inflate(layoutResource, null);

        // 4. 往DecorView中添加子View
        // 即文章开头介绍DecorView时提到的布局格式,那只是一个例子,根据主题样式不同,加载不同的布局。
        decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT)); 
        mContentRoot = (ViewGroup) in;

        // 5. 这里获取的是mContentParent = 即为内容栏(content)对应的DecorView = FrameLayout子类
        ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT); 
      
        return contentParent;
    }

概要:
ここに画像を挿入説明この場合、トップビュー(DecorView)は、レイアウトファイル&アクティビティセットを追加するために作成されました。このとき、トップレベルのビュー(DecorView)はまだ、すなわち目に見えない、表示されました。

二.DecorView表示

//代码片5(ActivityThread类)
final void handleResumeActivity(IBinder token,
            boolean clearHide, boolean isForward, boolean reallyResume) {

            ActivityClientRecord r = performResumeActivity(token, clearHide);

            if (r != null) {
                final Activity a = r.activity;
                  if (r.window == null && !a.mFinished && willBeVisible) {
                // 1. 获取Window实例中的Decor对象
                r.window = r.activity.getWindow();
                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;

                // 3. DecorView被添加进WindowManager了
                // 此时,还是不可见
                if (a.mVisibleFromClient) {
                    a.mWindowAdded = true;
                    
                    wm.addView(decor, l);
                }

                // 4. 此处设置DecorView对用户可见
                if (!r.activity.mFinished && willBeVisible
                    && r.activity.mDecor != null && !r.hideForNow) {
                     if (r.activity.mVisibleFromClient) {
                            r.activity.makeVisible();
                            // —>>分析3
                        }
                    }
            }

//代码片6(Activity类)
void makeVisible() {
   if (!mWindowAdded) {
            ViewManager wm = getWindowManager();
            // 1. 将DecorView添加到WindowManager ->>分析4
            wm.addView(mDecor, getWindow().getAttributes());
            mWindowAdded = true;
        }
        // 2. DecorView可见
        mDecor.setVisibility(View.VISIBLE);
    }

//代码片7(WindowManagerImpl类)
/**
  * 分析4:wm.addView
  * 作用:WindowManager = 1个接口,由WindowManagerImpl类实现
  */
  public final class WindowManagerImpl implements WindowManager {    
    private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
    ...
    @Override
    public void addView(View view, ViewGroup.LayoutParams params) {
        mGlobal.addView(view, params, mDisplay, mParentWindow); ->>分析5
    }
}
//代码片8(WindowManagerGlobal类)
/**
  * 分析5:WindowManagerGlobal 的addView()
  */
  public void addView(View view, ViewGroup.LayoutParams params,Display display, Window parentWindow) {

             final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams)params;

             ...

             synchronized (mLock) {

             // 1. 实例化一个ViewRootImpl对象
             ViewRootImpl root;
             root = new ViewRootImpl(view.getContext(), display);
             view.setLayoutParams(wparams);

             mViews.add(view);
             mRoots.add(root);
             mParams.add(wparams);
             }

             // 2. WindowManager将DecorView实例对象交给ViewRootImpl 绘制View
             try {
                  root.setView(view, wparams, panelParentView);   // ->> 分析6
                	}catch (RuntimeException e) {
               }
            }
 }

//代码片9(ViewRootImpl类)
**
  * 分析6:ViewRootImpl.setView()
  */
    public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
                requestLayout(); // ->>分析7
    }

//代码片10(ViewRootImpl类)
/**
  * 分析7:ViewRootImpl.requestLayout()
  */
    @Override
    public void requestLayout() {

        if (!mHandlingLayoutInLayoutRequest) {
        	// 1. 检查是否在主线程
            checkThread();
            mLayoutRequested = true;//mLayoutRequested 是否measure和layout布局。
            // 2. ->>分析8
            scheduleTraversals();
        }
    }
//代码片11(ViewRootImpl类)
/**
  * 分析8:ViewRootImpl.scheduleTraversals()
  */
    void scheduleTraversals() {
        if (!mTraversalScheduled) {
            mTraversalScheduled = true;
            mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();

            // 通过mHandler.post()发送一个runnable,在run()方法中去处理绘制流程
            // 与ActivityThread的Handler消息传递机制相似
            // ->>分析9
            mChoreographer.postCallback(
                    Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
            ``````
        }
    }
//代码片12(ViewRootImpl类)
/**
  * 分析9:Runnable类的子类对象mTraversalRunnable
  * 作用:在run()方法中去处理绘制流程
  */
    final class TraversalRunnable implements Runnable {
        @Override
        public void run() {
            doTraversal(); // ->>分析10
        }
    }
//代码片13(ViewRootImpl类)
/**
    * 分析10:doTraversal()
    */
    void doTraversal() {
            mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);

            performTraversals(); 
            // 最终会调用performTraversals(),从而开始View绘制的3大流程:Measure、Layout、Draw
    }
    // 注:
    //    a. 我们知道ViewRootImpl中W类是Binder的Native端,用于接收WmS处理操作
    //    b. 因W类的接收方法是在线程池中的,故可通过Handler将事件处理切换到主线程中

上記プロセスは、以下れる:
(1)でDecorViewウィンドウマネージャにオブジェクトを追加
ViewRootImplオブジェクトを作成する(2)
(3)DecorView ViewRootImplオブジェクトのオブジェクトウィンドウマネージャに
ViewRootImplオブジェクトがメインスレッドハンドラによってトラバーサル操作をトリガするメッセージを送信する(4) :performTraversals();表示の描画処理を実行するためのこの方法(測定、レイアウト、ドロー)

種々の変更は&その中の処理を完了するために(例えば、コントロール・ツリー再描画要求からWMS寸法変化から属性変更ウィンドウが(performTraversalsイニシエータかもしれない)、受信したオブジェクトを呼び出すViewRootImpl。

から見ることができます:
コントロールツリー整然とした作業を駆動するために(1)時間と時間を再びperformTraversals()の呼び出し
(2)このメソッドが正常に動作していないならば、全体のコントロールツリーが死んだ状態になります
ので(3)performTraversals()と言うことができますオブジェクトクラスは、コアであるViewRootImpl

ビューが実行される()performTraversalsの描画です。ビューの描画処理(測定、レイアウト、ドロー)のうち3つは、後で学ぶために来ます。

公開された81元の記事 ウォン称賛37 ビュー50000 +

おすすめ

転載: blog.csdn.net/gaolh89/article/details/104027903