frameworks之Activity添加View
- 互联网
- 2025-08-26 12:36:01

frameworks 之 Activity添加View 1 LaunchActivityItem1.1 Activity 创建1.2 PhoneWindow 创建1.3 DecorView 创建 2 ResumeActivityItem 讲解 Activity加载View的时机和流程 涉及到的类如下 frameworks/base/core/java/android/app/Activity.javaframeworks/base/services/core/java/com/android/server/wm/ActivityTaskSupervisor.javaframeworks/base/core/java/com/android/internal/policy/PhoneWindow.javaframeworks/base/core/java/android/view/WindowManagerImpl.java
从之前文章Activity启动流程可知,最终会到 ActivityTaskSupervisor 的 realStartActivityLocked 方法,而 realStartActivityLocked 最终会执行 2个主要步骤 就是 LaunchActivityItem 和 ResumeActivityItem。
1 LaunchActivityItem 1.1 Activity 创建LaunchActivityItem 的 又会调用 ActivityThread的 handleLaunchActivity 方法
public void execute(ClientTransactionHandler client, IBinder token, PendingTransactionActions pendingActions) { Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart"); ActivityClientRecord r = client.getLaunchingActivity(token); client.handleLaunchActivity(r, pendingActions, null /* customIntent */); Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); }handleLaunchActivity 又会调用 performLaunchActivity 方法
public Activity handleLaunchActivity(ActivityClientRecord r, PendingTransactionActions pendingActions, Intent customIntent) { ... final Activity a = performLaunchActivity(r, customIntent); ... return a; }performLaunchActivity 方法中
会通过反射调用对应的 Activity调用 Activity的 attach 方法创建phoneWindow通过 callActivityOnCreate 执行 Activity的 onCreate方法设置 ActivityClientRecord 状态为 ON_CREATE private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) { ... ContextImpl appContext = createBaseContextForActivity(r); // 进行反射创建对应的 Activity对象 Activity activity = null; try { java.lang.ClassLoader cl = appContext.getClassLoader(); activity = mInstrumentation.newActivity( cl, component.getClassName(), r.intent); StrictMode.incrementExpectedActivityCount(activity.getClass()); r.intent.setExtrasClassLoader(cl); r.intent.prepareToEnterProcess(isProtectedComponent(r.activityInfo), appContext.getAttributionSource()); if (r.state != null) { r.state.setClassLoader(cl); } } catch (Exception e) { if (!mInstrumentation.onException(activity, e)) { throw new RuntimeException( "Unable to instantiate activity " + component + ": " + e.toString(), e); } } try { Application app = r.packageInfo.makeApplication(false, mInstrumentation); if (activity != null) { ... // 调用 attach方法创建对应的的phoneView和 windowMangerImpl 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, r.assistToken, r.shareableActivityToken); ... r.activity = activity; // 触发Activity的 onCreate方法 if (r.isPersistable()) { mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState); } else { mInstrumentation.callActivityOnCreate(activity, r.state); } ... } // 设置 ActivityRecord状态为 ON_CREATE r.setState(ON_CREATE); } catch (SuperNotCalledException e) { throw e; } catch (Exception e) { if (!mInstrumentation.onException(activity, e)) { throw new RuntimeException( "Unable to start activity " + component + ": " + e.toString(), e); } } return activity; } 1.2 PhoneWindow 创建查看上面 Attach 方法
创建了 PhoneWindow调用 phoneWindow的setWindowManager 方法 创建对应 WindowManagerImpl 对象。将创建的WindowManagerImpl 赋值给 mWindowManager final void attach(Context context, ActivityThread aThread...) { ... // 初始化 PhoneWindow mWindow = new PhoneWindow(this, window, activityConfigCallback); ... // 初始化 并设置WindowManager到phoneWindow对应的变量 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()); } // 将上一步通过 setWindowManager 创建WindowManagerImpl并赋值给 mWindowManager mWindowManager = mWindow.getWindowManager(); } 1.3 DecorView 创建执行了 Activity onCreate 方法后 ,我们就会对其调用 setContentView 将要显示的布局ID创建创建视图,setContentView 方法又会调用 phoneWindow的setContentView方法
public void setContentView(@LayoutRes int layoutResID) { getWindow().setContentView(layoutResID); initWindowDecorActionBar(); }phoneWindow的setContentView主要做了
判断 mContentParent 是否为空(放应用要显示的布局容器),为空的话 则调用 installDecor 方法,创建 DecorView 和 内容容器 mContentParent调用 inflate 将布局加载到 mContentParent 布局容器中 public void setContentView(int layoutResID) { // 如果contentview为空则加载decorView if (mContentParent == null) { installDecor(); } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) { mContentParent.removeAllViews(); } if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) { final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID, getContext()); transitionTo(newScene); } else { // 将对应的布局加载到对应的内容区域 mLayoutInflater.inflate(layoutResID, mContentParent); } ... }其中 installDecor 方法主要逻辑
判断 mDecor 是否为空 ,为空的话调用 generateDecor 方法**(直接new DecorView),,并赋值**判断 mContentParent 是否为空,为空的话 调用 generateLayout() 方法获取对应的容器.(里面会通过feature 加载对应的布局,然后获取R.id.content的控件),并返回。根据属性 设置对应的标题。 private void installDecor() { mForceDecorInstall = false; // 为空则创建 DecorView if (mDecor == null) { mDecor = generateDecor(-1); mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS); mDecor.setIsRootNamespace(true); if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) { mDecor.postOnAnimation(mInvalidatePanelMenuRunnable); } } else { mDecor.setWindow(this); } // 为空则获取 decorView 用布局加载好里面的id为content的viewgroup if (mContentParent == null) { mContentParent = generateLayout(mDecor); ... mTitleView = findViewById(R.id.title); if (mTitleView != null) { if ((getLocalFeatures() & (1 << FEATURE_NO_TITLE)) != 0) { final View titleContainer = findViewById(R.id.title_container); if (titleContainer != null) { titleContainer.setVisibility(View.GONE); } else { mTitleView.setVisibility(View.GONE); } mContentParent.setForeground(null); } else { mTitleView.setText(mTitle); } } } } }generateLayout 主要
获取一系列属性调用 getLocalFeatures 生成对应的 features,根据获取到的属性获取对应的布局ID赋值到 layoutResource调用 decorView 的 onResourcesLoaded 方法 inflage出对应的布局,并通过 addView添加到 decorView,赋值给对应的mContentRoot 属性。根据mDecorView获取ID为 R.id.content的内容容器,并返回出去 protected ViewGroup generateLayout(DecorView decor) { ... // 获取设置一系列属性 mIsFloating = a.getBoolean(R.styleable.Window_windowIsFloating, false); int flagsToUpdate = (FLAG_LAYOUT_IN_SCREEN|FLAG_LAYOUT_INSET_DECOR) & (~getForcedWindowFlags()); ... // Inflate the window decor. // 获取对应的 layout布局文件 int layoutResource; int features = getLocalFeatures(); // System.out.println("Features: 0x" + Integer.toHexString(features)); if ((features & ((1 << FEATURE_LEFT_ICON) | (1 << FEATURE_RIGHT_ICON))) != 0) { if (mIsFloating) { TypedValue res = new TypedValue(); getContext().getTheme().resolveAttribute( R.attr.dialogTitleIconsDecorLayout, res, true); layoutResource = res.resourceId; } else { layoutResource = R.layout.screen_title_icons; } // XXX Remove this once action bar supports these features. removeFeature(FEATURE_ACTION_BAR); // System.out.println("Title Icons!"); } else if ((features & ((1 << FEATURE_PROGRESS) | (1 << FEATURE_INDETERMINATE_PROGRESS))) != 0 && (features & (1 << FEATURE_ACTION_BAR)) == 0) { // Special case for a window with only a progress bar (and title). // XXX Need to have a no-title version of embedded windows. layoutResource = R.layout.screen_progress; // System.out.println("Progress!"); } else if ((features & (1 << FEATURE_CUSTOM_TITLE)) != 0) { // Special case for a window with a custom title. // If the window is floating, we need a dialog layout if (mIsFloating) { TypedValue res = new TypedValue(); getContext().getTheme().resolveAttribute( R.attr.dialogCustomTitleDecorLayout, res, true); layoutResource = res.resourceId; } else { layoutResource = R.layout.screen_custom_title; } // XXX Remove this once action bar supports these features. removeFeature(FEATURE_ACTION_BAR); } else if ((features & (1 << FEATURE_NO_TITLE)) == 0) { // If no other features and not embedded, only need a title. // If the window is floating, we need a dialog layout if (mIsFloating) { TypedValue res = new TypedValue(); getContext().getTheme().resolveAttribute( R.attr.dialogTitleDecorLayout, res, true); layoutResource = res.resourceId; } else if ((features & (1 << FEATURE_ACTION_BAR)) != 0) { layoutResource = a.getResourceId( R.styleable.Window_windowActionBarFullscreenDecorLayout, R.layout.screen_action_bar); } else { layoutResource = R.layout.screen_title; } // System.out.println("Title!"); } else if ((features & (1 << FEATURE_ACTION_MODE_OVERLAY)) != 0) { layoutResource = R.layout.screen_simple_overlay_action_mode; } else { // Embedded, so no decoration is needed. layoutResource = R.layout.screen_simple; // System.out.println("Simple!"); } mDecor.onResourcesLoaded(mLayoutInflater, layoutResource); // 根据mDecorView获取ID为 R.id.content ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT); if (contentParent == null) { throw new RuntimeException("Window couldn't find content container view"); } ... return contentParent; } 2 ResumeActivityItem经过 onCreate 视图view都创建准备好后,就会进入 resume阶段 ResumeActivityItem 又会执行对应的 handleResumeActivity 方法。
public void execute(ClientTransactionHandler client, ActivityClientRecord r, PendingTransactionActions pendingActions) { Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityResume"); // 执行 ActivityThread 的 handleResumeActivity client.handleResumeActivity(r, true /* finalStateRequest */, mIsForward, "RESUME_ACTIVITY"); Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); }handleResumeActivity 方法
从 ActivityClientRecord 取出 创建的 Activity,。将 decorView 设置为 INVISIBLE,将对应的 LayoutParams type 层级设置为 WindowManager.LayoutParams.TYPE_BASE_APPLICATION调用 phoneWindow 创建的 WindowManagerImpl(attach创建) ,调用 addView 将 decorView添加到 WMS中。 public void handleResumeActivity(ActivityClientRecord r, boolean finalStateRequest, boolean isForward, String reason) { ... final Activity a = r.activity; ... final int forwardBit = isForward ? WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION : 0; // If the window hasn't yet been added to the window manager, // and this guy didn't finish itself or start another activity, // then go ahead and add the window. boolean willBeVisible = !a.mStartedActivity; if (!willBeVisible) { willBeVisible = ActivityClient.getInstance().willActivityBeVisible( a.getActivityToken()); } if (r.window == null && !a.mFinished && willBeVisible) { // 赋值 phoneWindow 给ActivityClientRecord r.window = r.activity.getWindow(); View decor = r.window.getDecorView(); decor.setVisibility(View.INVISIBLE); ViewManager wm = a.getWindowManager(); WindowManager.LayoutParams l = r.window.getAttributes(); // 将 decor赋值给activity a.mDecor = decor; // 设置Activity的层级为application l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION; l.softInputMode |= forwardBit; ... // 将decorView 通过 wms添加到容器中 if (a.mVisibleFromClient) { if (!a.mWindowAdded) { a.mWindowAdded = true; wm.addView(decor, l); } } } }WindowManagerImpl 添加时候 又会调用 全局单例WindowManagerGlobal 添加
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) { applyTokens(params); mGlobal.addView(view, params, mContext.getDisplayNoVerify(), mParentWindow, mContext.getUserId()); }addView中 会调用
创建对应的 ViewRootImpl将对应参数添加到各自的数组中调用 ViewRootImpl 的 setVIew 开始执行添加视图的 3步曲 (addToDisplayAsUser, relayout, finishDraw) public void addView(View view, ViewGroup.LayoutParams params, Display display, Window parentWindow, int userId) { if (view == null) { throw new IllegalArgumentException("view must not be null"); } if (display == null) { throw new IllegalArgumentException("display must not be null"); } if (!(params instanceof WindowManager.LayoutParams)) { throw new IllegalArgumentException("Params must be WindowManager.LayoutParams"); } final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params; // 如果不为空则认为子窗口添加,通过 adjustLayoutParamsForSubWindow 补全对应的参数 如title 和 token if (parentWindow != null) { parentWindow.adjustLayoutParamsForSubWindow(wparams); } else { // If there's no parent, then hardware acceleration for this view is // set from the application's hardware acceleration setting. final Context context = view.getContext(); if (context != null && (context.getApplicationInfo().flags & ApplicationInfo.FLAG_HARDWARE_ACCELERATED) != 0) { wparams.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED; } } // 创建对应的 ViewRootImpl ViewRootImpl root; View panelParentView = null; synchronized (mLock) { // Start watching for system property changes. if (mSystemPropertyUpdater == null) { mSystemPropertyUpdater = new Runnable() { @Override public void run() { synchronized (mLock) { for (int i = mRoots.size() - 1; i >= 0; --i) { mRoots.get(i).loadSystemProperties(); } } } }; SystemProperties.addChangeCallback(mSystemPropertyUpdater); } // 从 mViews 获取该view是否已添加 int index = findViewLocked(view, false); if (index >= 0) { // 判断该view是否在移除 if (mDyingViews.contains(view)) { // Don't wait for MSG_DIE to make it's way through root's queue. mRoots.get(index).doDie(); } else { throw new IllegalStateException("View " + view + " has already been added to the window manager."); } // The previous removeView() had not completed executing. Now it has. } // If this is a panel window, then find the window it is being // attached to for future reference. if (wparams.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW && wparams.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) { final int count = mViews.size(); for (int i = 0; i < count; i++) { if (mRoots.get(i).mWindow.asBinder() == wparams.token) { panelParentView = mViews.get(i); } } } // 创建viewRootImpl,该方法会通过 WindowManagerGlobal.getWindowSession() 获取session 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 { root.setView(view, wparams, panelParentView, userId); } catch (RuntimeException e) { // BadTokenException or InvalidDisplayException, clean up. if (index >= 0) { removeViewLocked(index, true); } throw e; } } }这样完成了Activity View的加载。
frameworks之Activity添加View由讯客互联互联网栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“frameworks之Activity添加View”
上一篇
图片粘贴上传实现