Activity 的 Window 创建主要流程

首先是在 ActivityThreadperformLaunchActivity() 方法中创建Activity实例,并调用 Activity attach  方法

xref: /frameworks/base/core/java/android/app/ActivityThread.java

package android.app;
......
public final class ActivityThread extends ClientTransactionHandler {
    /** @hide */
    public static final String TAG = "ActivityThread";
    ......

    /**  Core implementation of activity launch. */
    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        ActivityInfo aInfo = r.activityInfo;
        ......
        
        ContextImpl appContext = createBaseContextForActivity(r);
        Activity activity = null;
        try {
            java.lang.ClassLoader cl = appContext.getClassLoader();
            
            //通过类加载器cl创建Activity实例
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
            StrictMode.incrementExpectedActivityCount(activity.getClass());
            r.intent.setExtrasClassLoader(cl);
            r.intent.prepareToEnterProcess();
            if (r.state != null) {
                r.state.setClassLoader(cl);
            }
        } catch (Exception e) {
        
          ......

         }
         
         ......

          try {
            Application app = r.packageInfo.makeApplication(false, mInstrumentation);

            ......

            if (activity != null) {
                CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
                Configuration config = new Configuration(mCompatConfiguration);
                if (r.overrideConfig != null) {
                    config.updateFrom(r.overrideConfig);
                }
                ......
                Window window = null;
                ......
                appContext.setOuterContext(activity);
                
                //调用Activity的attach方法,关联运行过程中所依赖的上下文环境变量
                activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config,
                        r.referrer, r.voiceInteractor, window, r.configCallback);
              if (customIntent != null) {
                    activity.mIntent = customIntent;
                }
               ......

        } catch (SuperNotCalledException e) {
            throw e;

        } catch (Exception e) {
            ......
        }

        return activity;
    }

 

进入 Activity 的 attach 方法

xref: /frameworks/base/core/java/android/app/Activity.java

package android.app;

......

public class Activity extends ContextThemeWrapper
        implements LayoutInflater.Factory2,
        //实现了Window的 Callback 接口
        Window.Callback, KeyEvent.Callback,
        OnCreateContextMenuListener, ComponentCallbacks2,
        Window.OnWindowDismissedCallback, WindowControllerCallback,
        AutofillManager.AutofillClient {
    private static final String TAG = "Activity";
    private static final boolean DEBUG_LIFECYCLE = false;

    ......

    //定义mWindow、mDecor、mWindowManager
    private Window mWindow;

    private WindowManager mWindowManager;
    /*package*/ View mDecor = null;
    /*package*/ boolean mWindowAdded = false;

    ......

    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*/);

        //创建Activity所属的Window对象
        mWindow = new PhoneWindow(this, window, activityConfigCallback);
        //设置回调接口
        mWindow.setWindowControllerCallback(this);
        mWindow.setCallback(this);
        mWindow.setOnWindowDismissedCallback(this);
        mWindow.getLayoutInflater().setPrivateFactory(this);

        ......

        //通过Window 设置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());
        }
        mWindowManager = mWindow.getWindowManager();//获取WindowManager
        ......
   }


   /**
     * 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)
     */
    //直接调用了Window的setContentView方法
    public void setContentView(@LayoutRes int layoutResID) {
        getWindow().setContentView(layoutResID);
        initWindowDecorActionBar();
    }

    public Window getWindow() {
        return mWindow;
    }

接下来进入 PhoneWindow 的 setContentView 方法

xref: /frameworks/base/core/java/com/android/internal/policy/PhoneWindow.java

package com.android.internal.policy;
......

public class PhoneWindow extends Window implements MenuBuilder.Callback {

    private final static String TAG = "PhoneWindow";
    ......

    // This is the top-level view of the window, containing the window decor.
    private DecorView mDecor;//将在  generateDecor(-1) 方法中创建
    
    ......

    // 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;//将在 generateLayout(mDecor) 方法中创建
    ......
    private LayoutInflater mLayoutInflater;
    ......
    //在其中一个构造方法中获取 mLayoutInflater 对象
    public PhoneWindow(Context context) {
        super(context);
        mLayoutInflater = LayoutInflater.from(context);
    }
    
    /***
     *
     *
    
    1.首先创建 DecorView,DecorView是一个FrameLayout,是Activity中的顶级View
    DecorView包含标题栏和内容栏两个部分
    
    2.之后直接通过我们常用的LayoutInflater的inflate方法
    直接将我们在XML文件中定义的布局inflate进 DecorView 的内容栏里面
    
     ***/
    @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();//创建DecorView,获取mContentParent 
        } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
            mContentParent.removeAllViews();
        }

        if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
            final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
                    getContext());
            transitionTo(newScene);
        } else {
            //直接将对应的布局文件 inflate 进ViewGroup
            mLayoutInflater.inflate(layoutResID, mContentParent);
        }
        mContentParent.requestApplyInsets();
        final Callback cb = getCallback();
        if (cb != null && !isDestroyed()) {
            cb.onContentChanged();//将会回调Activity中对应的方法
        }
        mContentParentExplicitlySet = true;
    }

    //以下是创建DecorView 和 mContentParent的过程
    private void installDecor() {
        mForceDecorInstall = false;
        if (mDecor == null) {
            mDecor = generateDecor(-1);//创建DecorView
            mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
            mDecor.setIsRootNamespace(true);
            if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
                mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
            }
        } else {
            mDecor.setWindow(this);
        }
        if (mContentParent == null) {
            mContentParent = generateLayout(mDecor);//创建ViewGroup类型的mContentParent 
        
        ......

     }


   protected DecorView generateDecor(int featureId) {
        // System process doesn't have application context and in that case we need to directly use
        // the context we have. Otherwise we want the application context, so we don't cling to the
        // activity.
        Context context;
        if (mUseDecorContext) {
            Context applicationContext = getContext().getApplicationContext();
            if (applicationContext == null) {
                context = getContext();
            } else {
                context = new DecorContext(applicationContext, getContext());
                if (mTheme != -1) {
                    context.setTheme(mTheme);
                }
            }
        } else {
            context = getContext();
        }
        return new DecorView(context, featureId, this, getAttributes());
    }


  protected ViewGroup generateLayout(DecorView decor) {
        // Apply data from current theme.

        TypedArray a = getWindowStyle();
        ......

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

        return contentParent;
    }

    

其中 ID_ANDROID_CONTENT 这个id对应的 ViewGroup 就是 PhoneWindow 中的 mContentParent

在Window中有对应的定义如下

xref: /frameworks/base/core/java/android/view/Window.java

package android.view;
......
public abstract class Window {
    
    /**
     * The ID that the main layout in the XML layout file should have.
    */
    public static final int ID_ANDROID_CONTENT = com.android.internal.R.id.content;


以下是 DecorView 的定义和PhoneWindow在同一路径下,继承了 FrameLayout

xref: /frameworks/base/core/java/com/android/internal/policy/DecorView.java

package com.android.internal.policy;

public class DecorView extends FrameLayout implements RootViewSurfaceTaker, WindowCallbacks {

 

你可能感兴趣的:(Android开发笔记)