Android13 Activity attach流程分析

Activity的attach()方法是Android中的一个重要方法,用于将Activity与当前的上下文环境进行关联。在attach()方法中,Activity会完成一系列的初始化工作,包括与WindowManagerService建立联系、创建Window、加载布局文件等。attach代码如下:

//frameworks/base/core/java/android/app/Activity.java
public class Activity extends ContextThemeWrapper
        implements LayoutInflater.Factory2,
        Window.Callback, KeyEvent.Callback,
        OnCreateContextMenuListener, ComponentCallbacks2,
        Window.OnWindowDismissedCallback,
        ContentCaptureManager.ContentCaptureClient {


    Intent mIntent;
    String mReferrer;
    ActivityThread mMainThread;
    ActivityInfo mActivityInfo;
    Activity mParent;
    String mEmbeddedID;
    VoiceInteractor mVoiceInteractor;
    NonConfigurationInstances mLastNonConfigurationInstances;
    
    private IBinder mToken;
    private IBinder mAssistToken;
    private Thread mUiThread;
    private Window mWindow;
    private IBinder mToken;
    private IBinder mAssistToken;
    private IBinder mShareableActivityToken;
    private int mIdent;
    private Application mApplication;
    private ComponentName mComponent;
    private CharSequence mTitle;
    private Instrumentation mInstrumentation;
    private WindowManager mWindowManager;
    Configuration mCurrentConfig = Configuration.EMPTY;
    final FragmentController mFragments = FragmentController.createController(new HostCallbacks());
    
    public abstract LayoutInflater getLayoutInflater();


    private final WindowControllerCallback mWindowControllerCallback =
            new WindowControllerCallback() {
        /**
         * Moves the activity between {@link WindowConfiguration#WINDOWING_MODE_FREEFORM} windowing
         * mode and {@link WindowConfiguration#WINDOWING_MODE_FULLSCREEN}.
         *
         * @hide
         */
        @Override
        public void toggleFreeformWindowingMode() {
            ActivityClient.getInstance().toggleFreeformWindowingMode(mToken);
        }


        /**
         * Puts the activity in picture-in-picture mode if the activity supports.
         * @see android.R.attr#supportsPictureInPicture
         * @hide
         */
        @Override
        public void enterPictureInPictureModeIfPossible() {
            if (mActivityInfo.supportsPictureInPicture()) {
                enterPictureInPictureMode();
            }
        }


        @Override
        public boolean isTaskRoot() {
            return ActivityClient.getInstance().getTaskForActivity(
                    mToken, true /* onlyRoot */) >= 0;
        }


        /**
         * Update the forced status bar color.
         * @hide
         */
        @Override
        public void updateStatusBarColor(int color) {
            mTaskDescription.setStatusBarColor(color);
            setTaskDescription(mTaskDescription);
        }


        /**
         * Update the forced navigation bar color.
         * @hide
         */
        @Override
        public void updateNavigationBarColor(int color) {
            mTaskDescription.setNavigationBarColor(color);
            setTaskDescription(mTaskDescription);
        }


    }


    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, IBinder assistToken,
            IBinder shareableActivityToken) {
        attachBaseContext(context);


        mFragments.attachHost(null /*parent*/);


        mWindow = new PhoneWindow(this, window, activityConfigCallback);
        mWindow.setWindowControllerCallback(mWindowControllerCallback);
        mWindow.setCallback(this);
        mWindow.setOnWindowDismissedCallback(this);
        mWindow.getLayoutInflater().setPrivateFactory(this);
        if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
            mWindow.setSoftInputMode(info.softInputMode);
        }
        if (info.uiOptions != 0) {
            mWindow.setUiOptions(info.uiOptions);
        }
        mUiThread = Thread.currentThread();


        mMainThread = aThread; //ActivityThread 
        mInstrumentation = instr;
        mToken = token;
        mAssistToken = assistToken;
        mShareableActivityToken = shareableActivityToken;
        mIdent = ident;
        mApplication = application;
        mIntent = intent;
        mReferrer = referrer;
        mComponent = intent.getComponent();
        mActivityInfo = info;
        mTitle = title;
        mParent = parent;
        mEmbeddedID = id;
        mLastNonConfigurationInstances = lastNonConfigurationInstances;
        if (voiceInteractor != null) {
            if (lastNonConfigurationInstances != null) {
                mVoiceInteractor = lastNonConfigurationInstances.voiceInteractor;
            } else {
                mVoiceInteractor = new VoiceInteractor(voiceInteractor, this, this,
                        Looper.myLooper());
            }
        }


        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();
        mCurrentConfig = config;


        mWindow.setColorMode(info.colorMode);
        mWindow.setPreferMinimalPostProcessing(
                (info.flags & ActivityInfo.FLAG_PREFER_MINIMAL_POST_PROCESSING) != 0);


        getAutofillClientController().onActivityAttached(application);
        setContentCaptureOptions(application.getContentCaptureOptions());
    }
}

上面方法主要处理如下:

1、通过new的方式创建PhoneWindow对象。

2、调用Window的setWindowControllerCallback方法,设置WindowControllerCallback接口回调。

3、调用Window的setCallback,设置Callback接口回调。

4、调用Window的getLayoutInflater()方法获取LayoutInflater,然后调用LayoutInflater的setPrivateFactory放设置LayoutInflater工厂。

5、调用Window的setSoftInputMode方法,设置窗口软键盘交互模式。

6、调用Window的setUiOptions方法。

7、调用Window的setWindowManager,设置此窗口使用的窗口管理器。

8、如果此Window是子窗口(弹出窗口),就会调用此Window的setContainer,设置弹出窗口的容器视图。

9、调用Window的setColorMode方法,设置Windoe的颜色模式。

10、调用Window的setPreferMinimalPostProcessing方法,开启或关闭最低限度的后期处理。

11、调用Activity的getAutofillClientController方法,获取AutofillClientController对象,然后调用AutofillClientController对象的onActivityAttached方法。

12、调用Activity的setContentCaptureOptions方法,用于设置内容捕获选项。

下面分别进行分析:

new PhoneWindow

通过new的方式创建PhoneWindow对象,PhoneWindow是在Activity的attach中创建的,在Activity的attach中通过new的方式创建PhoneWindow对象,PhoneWindow是系统中提供一个具体实现Window的子类,其主要作用是提供了Android应用程序的界面UI,包括窗口、标题栏、动画效果等,同时还提供了与操作系统交互的支持,例如在系统状态栏提供应用程序的图标和通知,提供电话功能等,PhoneWindow的构造方法如下:

//frameworks/base/core/java/com/android/internal/policy/PhoneWindow.java
public class PhoneWindow extends Window implements MenuBuilder.Callback {
    private boolean mUseDecorContext = false;
    private DecorView mDecor;
    private float mElevation;
    private boolean mLoadElevation = true;
    private boolean mForceDecorInstall = false;
    private final ProxyOnBackInvokedDispatcher mProxyOnBackInvokedDispatcher;
    private boolean mSupportsPictureInPicture;
    private ActivityConfigCallback mActivityConfigCallback;


    public PhoneWindow(@UiContext Context context, Window preservedWindow,
            ActivityConfigCallback activityConfigCallback) {
        this(context);
        // Only main activity windows use decor context, all the other windows depend on whatever
        // context that was given to them.
        mUseDecorContext = true;
        if (preservedWindow != null) {
            mDecor = (DecorView) preservedWindow.getDecorView();
            mElevation = preservedWindow.getElevation();
            mLoadElevation = false;
            mForceDecorInstall = true;
            // If we're preserving window, carry over the app token from the preserved
            // window, as we'll be skipping the addView in handleResumeActivity(), and
            // the token will not be updated as for a new window.
            getAttributes().token = preservedWindow.getAttributes().token;
            mProxyOnBackInvokedDispatcher.setActualDispatcher(
                    preservedWindow.getOnBackInvokedDispatcher());
        }
        // Even though the device doesn't support picture-in-picture mode,
        // an user can force using it through developer options.
        boolean forceResizable = Settings.Global.getInt(context.getContentResolver(),
                DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES, 0) != 0;
        mSupportsPictureInPicture = forceResizable || context.getPackageManager().hasSystemFeature(
                PackageManager.FEATURE_PICTURE_IN_PICTURE);
        mActivityConfigCallback = activityConfigCallback;
    }
}

Window setWindowControllerCallback

调用Window的setWindowControllerCallback方法,设置WindowControllerCallback接口回调:

//frameworks/base/core/java/android/view/Window.java
public abstract class Window {
    private WindowControllerCallback mWindowControllerCallback;
    public final void setWindowControllerCallback(WindowControllerCallback wccb) {
        mWindowControllerCallback = wccb;
    }
}

Window setCallback

调用Window的setCallback,设置Callback接口回调:

//frameworks/base/core/java/android/view/Window.java
public abstract class Window {
    public void setCallback(Callback callback) {
        mCallback = callback;
    }
}

Window setOnWindowDismissedCallback

调用Window的setOnWindowDismissedCallback,设置OnWindowDismissedCallback接口回调:

//frameworks/base/core/java/android/view/Window.java
public abstract class Window {
    public final void setOnWindowDismissedCallback(OnWindowDismissedCallback dcb) {
        mOnWindowDismissedCallback = dcb;
    }
}

Window getLayoutInflater setPrivateFactory

mWindow.getLayoutInflater().setPrivateFactory(this);

LayoutInflater是Android系统中用于解析布局文件的类,可以将布局文件解析为相应的视图对象,在Android应用程序中,通常使用LayoutInflater实例来获取一个具有视图层次结构的对象,然后将该对象附件到Activity或Fragment等组件中。

通过Window的getLayoutInflater方法,获取LayoutInflater:

//frameworks/base/core/java/android/view/Window.java
public abstract class Window {
    public abstract LayoutInflater getLayoutInflater();
}

PhoneWindow setPrivateFactory

Window的getLayoutInflater为抽象方法,由其子类PhoneWindow实现:

frameworks/base/core/java/com/android/internal/policy/PhoneWindow.java
public class PhoneWindow extends Window implements MenuBuilder.Callback {
    public LayoutInflater getLayoutInflater() {
        return mLayoutInflater;
    }
}

调用LayoutInflater的setPrivateFactory方法:

//frameworks/base/core/java/android/view/LayoutInflater.java
public abstract class LayoutInflater {
    private Factory2 mPrivateFactory;
    public void setPrivateFactory(Factory2 factory) {
        if (mPrivateFactory == null) {
            mPrivateFactory = factory;
        } else {
            mPrivateFactory = new FactoryMerger(factory, factory, mPrivateFactory, mPrivateFactory);
        }
    }
}

new FactoryMerger

通过new的方式创建FactoryMerger对象,FactoryMerger为LayoutInflater的内部类。

PhoneLayoutInflater的FactoryMerger是一个用于合并多个Factory的辅助类。它继承自LayoutInflater.Factory2接口,并实现了Factory2的方法。FactoryMerger的作用是将多个Factory按照优先级顺序进行合并,以便在解析布局文件时按照指定的顺序查找合适的Factory来创建View。

FactoryMerger的构造方法接收一个Factory数组作为参数,这些Factory按照优先级从高到低的顺序排列。在FactoryMerger的内部,它会遍历这些Factory,并依次调用它们的onCreateView方法来创建View。如果某个Factory的onCreateView方法返回了非空的View,那么FactoryMerger会直接返回该View,不再继续遍历后面的Factory。

FactoryMerger代码如下:

//frameworks/base/core/java/android/view/LayoutInflater.java
public abstract class LayoutInflater {
    private static class FactoryMerger implements Factory2 {
        private final Factory mF1, mF2;
        private final Factory2 mF12, mF22;


        FactoryMerger(Factory f1, Factory2 f12, Factory f2, Factory2 f22) {
            mF1 = f1;
            mF2 = f2;
            mF12 = f12;
            mF22 = f22;
        }


        @Nullable
        public View onCreateView(@NonNull String name, @NonNull Context context,
                @NonNull AttributeSet attrs) {
            View v = mF1.onCreateView(name, context, attrs);
            if (v != null) return v;
            return mF2.onCreateView(name, context, attrs);
        }


        @Nullable
        public View onCreateView(@Nullable View parent, @NonNull String name,
                @NonNull Context context, @NonNull AttributeSet attrs) {
            View v = mF12 != null ? mF12.onCreateView(parent, name, context, attrs)
                    : mF1.onCreateView(name, context, attrs);
            if (v != null) return v;
            return mF22 != null ? mF22.onCreateView(parent, name, context, attrs)
                    : mF2.onCreateView(name, context, attrs);
        }
    }
}

Window setSoftInputMode

调用Window的setSoftInputMode方法,设置窗口软键盘交互模式:

//frameworks/base/core/java/android/view/Window.java
public abstract class Window {
    public void setSoftInputMode(int mode) {
        final WindowManager.LayoutParams attrs = getAttributes();
        if (mode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
            attrs.softInputMode = mode;
            mHasSoftInputMode = true;
        } else {
            mHasSoftInputMode = false;
        }
        dispatchWindowAttributesChanged(attrs); //窗口属性已更改调度
    }


    public final WindowManager.LayoutParams getAttributes() {
        return mWindowAttributes;
    }
}

dispatchWindowAttributesChanged

调用dispatchWindowAttributesChanged方法,通过回调通知窗口属性已更改:

//frameworks/base/core/java/android/view/Window.java
public abstract class Window {
    protected void dispatchWindowAttributesChanged(WindowManager.LayoutParams attrs) {
        if (mCallback != null) {
            mCallback.onWindowAttributesChanged(attrs); //每当当前窗口属性发生更改时,都会调用此函数。
        }
    }
}

Window setUiOptions

调用Window的setUiOptions方法,

//frameworks/base/core/java/android/view/Window.java
public abstract class Window {
    public void setUiOptions(int uiOptions) { }
}

Window的setUiOptions处理为空,我们看看PhoneWindow的setUiOptions方法:

PhoneWindow setUiOptions

frameworks/base/core/java/com/android/internal/policy/PhoneWindow.java
public class PhoneWindow extends Window implements MenuBuilder.Callback {
    private int mUiOptions = 0;
    public void setUiOptions(int uiOptions) {
        mUiOptions = uiOptions;
    }
}

Window setWindowManager

调用Window的setWindowManager,设置此窗口使用的窗口管理器:

//frameworks/base/core/java/android/view/Window.java
public abstract class Window {
    private IBinder mAppToken;
    private String mAppName;
    private boolean mHardwareAccelerated;
    private WindowManager mWindowManager;
    public void setWindowManager(WindowManager wm, IBinder appToken, String appName,
            boolean hardwareAccelerated) {
        mAppToken = appToken;
        mAppName = appName;
        mHardwareAccelerated = hardwareAccelerated;
        if (wm == null) {
            wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE); 
        }
        mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
    }
}

WindowManagerImpl createLocalWindowManager

调用WindowManagerImpl的createLocalWindowManager方法,WindowManagerImpl的WindowManager的一个具体实现类:

//frameworks/base/core/java/android/view/WindowManagerImpl.java
public final class WindowManagerImpl implements WindowManager {
    public WindowManagerImpl createLocalWindowManager(Window parentWindow) {
        return new WindowManagerImpl(mContext, parentWindow, mWindowContextToken);
    }
}

new WindowManagerImpl

WindowManagerImpl的构造方法:

//frameworks/base/core/java/android/view/WindowManagerImpl.java
public final class WindowManagerImpl implements WindowManager {


    public final Context mContext;
    private final Window mParentWindow;
    private final IBinder mWindowContextToken;


    private WindowManagerImpl(Context context, Window parentWindow,
            @Nullable IBinder windowContextToken) {
        mContext = context;
        mParentWindow = parentWindow;
        mWindowContextToken = windowContextToken;
    }
}

Window setContainer

如果此Window是子窗口(弹出窗口),就会调用此Window的setContainer,设置弹出窗口的容器视图:

//frameworks/base/core/java/android/view/Window.java
public abstract class Window {
    private Window mContainer;
    private int mFeatures;
    private int mLocalFeatures;


    public void setContainer(Window container) {
        mContainer = container;
        if (container != null) {
            // Embedded screens never have a title.
            mFeatures |= 1<<FEATURE_NO_TITLE;
            mLocalFeatures |= 1<<FEATURE_NO_TITLE;
            container.mHasChildren = true;
        }
    }
}

Window setColorMode

调用Window的setColorMode方法,设置Windoe的颜色模式:

//frameworks/base/core/java/android/view/Window.java
public abstract class Window {
    public void setColorMode(@ActivityInfo.ColorMode int colorMode) {
        final WindowManager.LayoutParams attrs = getAttributes();
        attrs.setColorMode(colorMode);
        dispatchWindowAttributesChanged(attrs);
    }


    public final WindowManager.LayoutParams getAttributes() {
        return mWindowAttributes;
    }
}

dispatchWindowAttributesChanged

调用dispatchWindowAttributesChanged方法,通过回调通知窗口属性已更改:

//frameworks/base/core/java/android/view/Window.java
public abstract class Window {
    protected void dispatchWindowAttributesChanged(WindowManager.LayoutParams attrs) {
        if (mCallback != null) {
            mCallback.onWindowAttributesChanged(attrs); //每当当前窗口属性发生更改时,都会调用此函数。
        }
    }
}

Window setPreferMinimalPostProcessing

调用Window的setPreferMinimalPostProcessing方法,开启或关闭最低限度的后期处理:

//frameworks/base/core/java/android/view/Window.java
public abstract class Window {
    private final WindowManager.LayoutParams mWindowAttributes =
        new WindowManager.LayoutParams();
    public void setPreferMinimalPostProcessing(boolean isPreferred) {
        mWindowAttributes.preferMinimalPostProcessing = isPreferred;
        dispatchWindowAttributesChanged(mWindowAttributes);
    }
}

Activity getAutofillClientController

调用Activity的getAutofillClientController方法,获取AutofillClientController对象:

//frameworks/base/core/java/android/app/Activity.java
public class Activity extends ContextThemeWrapper
        implements LayoutInflater.Factory2,
        Window.Callback, KeyEvent.Callback,
        OnCreateContextMenuListener, ComponentCallbacks2,
        Window.OnWindowDismissedCallback,
        ContentCaptureManager.ContentCaptureClient {


    private AutofillClientController mAutofillClientController;


    private AutofillClientController getAutofillClientController() {
        if (mAutofillClientController == null) {
            mAutofillClientController = new AutofillClientController(this);
        }
        return mAutofillClientController;
    }
}

AutofillClientController onActivityAttached

然后调用AutofillClientController对象的onActivityAttached方法:

AutofillClientController是Android系统中的一个类,用于管理自动填充功能的客户端。它负责与AutofillService进行通信,并处理自动填充请求和响应。

//frameworks/base/core/java/android/view/autofill/AutofillClientController.java
public final class AutofillClientController implements AutofillManager.AutofillClient, Dumpable {
    public void onActivityAttached(Application application) {
        mActivity.setAutofillOptions(application.getAutofillOptions());
    }
}

ContextWrapper setContentCaptureOptions

调用ContextWrapper的setContentCaptureOptions方法,用于设置内容捕获选项:

//frameworks/base/core/java/android/content/ContextWrapper.java
public class ContextWrapper extends Context {
    Context mBase;
    public void setContentCaptureOptions(@Nullable ContentCaptureOptions options) {
        if (mBase != null) {
            mBase.setContentCaptureOptions(options);
        }
    }
}
  • 22
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值