美文网首页
Activity结构

Activity结构

作者: 小O机 | 来源:发表于2022-06-30 16:39 被阅读0次

以下源码基于android 12.0.0_r3

// Activity.java
public class Activity extends ContextThemeWrapper
        implements LayoutInflater.Factory2,
        Window.Callback, KeyEvent.Callback,
        OnCreateContextMenuListener, ComponentCallbacks2,
        Window.OnWindowDismissedCallback,
        AutofillManager.AutofillClient, ContentCaptureManager.ContentCaptureClient {
        ...

        @UnsupportedAppUsage
        private Window mWindow;    // 其唯一实现类 -> PhoneWindow.java

        /**
         * Set the activity content from a layout resource.  The resource will be
         * inflated, adding all top-level views to the activity.
         *
         * @param layoutResID Resource ID to be inflated.
         *
         * @see #setContentView(android.view.View)
         * @see #setContentView(android.view.View, android.view.ViewGroup.LayoutParams)
         */
        public void setContentView(@LayoutRes int layoutResID) {
            getWindow().setContentView(layoutResID);    // 调到PhoneWindow#setContentView()

            ...
        }
    ...
}

// PhoneWindow.java
/**
* Android-specific Window.
* <p>
* todo: need to pull the generic functionality out into a base class
* in android.widget.
*
* @hide
*/
public class PhoneWindow extends Window implements MenuBuilder.Callback {
    ...

    // This is the top-level view of the window, containing the window decor.
    private DecorView mDecor;

    // This is the view in which the window contents are placed. It is either
    // mDecor itself, or a child of mDecor where the contents go.
    ViewGroup mContentParent;

    @Override
    public void setContentView(int layoutResID) {
        // Note: FEATURE_CONTENT_TRANSITIONS may be set in the process of installing the window
        // decor, when theme attributes and the like are crystalized. Do not check the feature
        // before this happens.
        if (mContentParent == null) {
            installDecor();
        }
        
        ...

        // 解析外部传入的layoutResID,并将mContentParent作为解析布局的根布局
        mLayoutInflater.inflate(layoutResID, mContentParent);
        
        ...
    }
    
    private void installDecor() {
        if (mDecor == null) {
                    // 创建DecorView
            mDecor = generateDecor(-1);
            
            ...
        } else {
            mDecor.setWindow(this);
        }

        if (mContentParent == null) {
                // 创建ContentParent(ViewGroup),用于作为外部布局的容器使用
            mContentParent = generateLayout(mDecor);

            ...
        }

    protected ViewGroup generateLayout(DecorView decor) {
        // 1. 根据当前主题设置decor样式
        // Apply data from current theme.
        // 代码省略
        ...
          
        // 2. 渲染decor
        // Inflate the window decor.
        int layoutResource;
        int features = getLocalFeatures();
        
        // 3. 根据features获取不同的title布局,比如FEATURE_NO_TITLE,FEATURE_ACTION_BAR,FEATURE_ACTION_MODE_OVERLAY
        // 代码省略
        ...

        // 通知DecorView 根据titile布局初始化mContentRoot
        mDecor.onResourcesLoaded(mLayoutInflater, layoutResource);

        ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
        
        ...

        return contentParent;
    }
}

// DecorView.java
public class DecorView extends FrameLayout implements RootViewSurfaceTaker, WindowCallbacks {
    ...

    // Action bar
    private ActionBarContextView mPrimaryActionModeView;    // 通过ViewStub懒加载 R.id.action_mode_bar_stub

    @UnsupportedAppUsage
    private PhoneWindow mWindow;

    ViewGroup mContentRoot;

   /**
    * 初始化mContentRoot。在PhoneWindow.generateLayout中调用
    */ 
    void onResourcesLoaded(LayoutInflater inflater, int layoutResource) {
        ...
        
        // 根据PhoneWindow.generateLayout中获取的title布局id渲染布局
        final View root = inflater.inflate(layoutResource, null);

        ...
        // 将生成的root添加到DecorView中作为根布局
        // Put it below the color views.
        addView(root, 0, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));

        mContentRoot = (ViewGroup) root;
    }

    @Override
    public void onDraw(Canvas c) {
        super.onDraw(c);
        // 将mWindow.mContentParent绘制到mContentRoot上
       /**
        * Draws the fallback background.
        *
        * @param boundsView The view determining with which bounds the background should be drawn.
        * @param root The view group containing the content.
        * @param c The canvas to draw the background onto.
        * @param content The view where the actual app content is contained in.
        * @param coveringView1 A potentially opaque view drawn atop the content
        * @param coveringView2 A potentially opaque view drawn atop the content
        */
        mBackgroundFallback.draw(this, mContentRoot, c, mWindow.mContentParent,
                mStatusColorViewState.view, mNavigationColorViewState.view);
    }

    ...
}
  1. Activity.attach(): 创建mWindow = new PhoneWindow()
  2. Activity.setContentView(): 调用PhoneWindow.setContentView()做了以下两件事:
  • 通过PhoneWindow.installDecor()初始化DecorView和ContentParent(ViewGroup,com.android.internal.R.id.content)。
  • 使用mLayoutInflater.inflate(layoutResID, mContentParent)将ContentView添加到mContentParent中,但此时mContentParent还只是一个游离的ViewGroup。
  1. DecorView.onDraw():将mWindow.mContentParent绘制到mContentRoot上。

以上,Activity的界面构成就已经清晰了:


Activity结构图

相关文章

网友评论

      本文标题:Activity结构

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