成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Android高手進階之Activity.setContentView渲染流程詳解

開發 前端
setContentView(R.layout.activity_main)這么簡簡單單的一段代碼做了事情可不簡單;接下來我們會跟著源碼大概走一遍這個方法,一起總結下。

[[418895]]

前言

setContentView(R.layout.activity_main)這么簡簡單單的一段代碼做了事情可不簡單;

接下來我們會跟著源碼大概走一遍這個方法,一起總結下

一、DecorView的創建

Activity.setContentView

  1. public void setContentView(@LayoutRes int layoutResID) { 
  2.      getWindow().setContentView(layoutResID); //最終調用mWindow的setContentView方法 
  3.      initWindowDecorActionBar(); 
  4.  } 

getWindow返回的是mWindow, mWindow在Activity的attach方法里被賦值,是個PhoneWindow對象。

(PhoneWindow是Window的唯一實現類)

  1. final void attach(Context context, ActivityThread aThread, 
  2.           Instrumentation instr, IBinder token, int ident, 
  3.           Application application, Intent intent, ActivityInfo info, 
  4.           CharSequence title, Activity parent, String id, 
  5.           NonConfigurationInstances lastNonConfigurationInstances, 
  6.           Configuration config, String referrer, IVoiceInteractor voiceInteractor, 
  7.           Window window, ActivityConfigCallback activityConfigCallback) { 
  8.       attachBaseContext(context); 
  9.       mFragments.attachHost(null /*parent*/); 
  10.       mWindow = new PhoneWindow(this, window, activityConfigCallback); 
  11.       ... 
  12.       mWindow.setWindowManager( //設置WindowManager 
  13.               (WindowManager)context.getSystemService(Context.WINDOW_SERVICE), 
  14.               mToken, mComponent.flattenToString(), 
  15.               (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0); 
  16.       if (mParent != null) { 
  17.           mWindow.setContainer(mParent.getWindow()); 
  18.       } 
  19.       mWindowManager = mWindow.getWindowManager(); 
  20.   } 

PhoneWindow.setContentView

幾個關鍵變量

1.mDecor 是Window的最頂層的View,是個FrameLayout。

2.mContentParent 是用來真正裝載Activity傳入的布局文件的容器,本身是個ViewGroup。

  1. public void setContentView(int layoutResID) { 
  2.        // Note: FEATURE_CONTENT_TRANSITIONS may be set in the process of installing the window 
  3.        // decor, when theme attributes and the like are crystalized. Do not check the feature 
  4.        // before this happens. 
  5.        if (mContentParent == null) { 
  6.            installDecor(); //如果mContentParent為空,則執行installDecor方法 
  7.        } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) { 
  8.            mContentParent.removeAllViews(); //否則remove掉mContentParent的所有子view 
  9.        } 
  10.        if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) { 
  11.            final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID, 
  12.                    getContext()); 
  13.            transitionTo(newScene); 
  14.        } else { 
  15.            mLayoutInflater.inflate(layoutResID, mContentParent); //將activity傳入的布局文件加載到mContentParent里 
  16.        } 
  17.        mContentParent.requestApplyInsets(); 
  18.        final Callback cb = getCallback(); 
  19.        if (cb != null && !isDestroyed()) { 
  20.            cb.onContentChanged(); 
  21.        } 
  22.        mContentParentExplicitlySet = true
  23.    } 

PhoneWindow.installDecor

  1. private void installDecor() { 
  2.        mForceDecorInstall = false
  3.        if (mDecor == null) { 
  4.            mDecor = generateDecor(-1); //如果之前沒有創建,直接創建一個 
  5.            mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS); 
  6.            mDecor.setIsRootNamespace(true); 
  7.            if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) { 
  8.                mDecor.postOnAnimation(mInvalidatePanelMenuRunnable); 
  9.            } 
  10.        } else { 
  11.            mDecor.setWindow(this); //將PhoneWindow傳遞給DecorView 
  12.        } 
  13.        if (mContentParent == null) { 
  14.            mContentParent = generateLayout(mDecor); //賦值mContentParent 
  15.        ... 
  16.    } 

PhoneWindow.installDecor

  1. protected DecorView generateDecor(int featureId) { 
  2.        // System process doesn't have application context and in that case we need to directly use 
  3.        // the context we have. Otherwise we want the application context, so we don't cling to the 
  4.        // activity. 
  5.        Context context; 
  6.        if (mUseDecorContext) { 
  7.            Context applicationContext = getContext().getApplicationContext(); 
  8.            if (applicationContext == null) { 
  9.                context = getContext(); 
  10.            } else { 
  11.                context = new DecorContext(applicationContext, getContext()); 
  12.                if (mTheme != -1) { 
  13.                    context.setTheme(mTheme); 
  14.                } 
  15.            } 
  16.        } else { 
  17.            context = getContext(); 
  18.        } 
  19.        return new DecorView(context, featureId, this, getAttributes()); //創建DecorView 
  20.    } 

PhoneWindow.generateLayout

這一步是挑選合適的DecorView布局文件并將其添加大盤DecorView,同時給mContentParent賦值。

  1. protected ViewGroup generateLayout(DecorView decor) { 
  2.         // Apply data from current theme. 
  3.         TypedArray a = getWindowStyle(); 
  4.         ...... 
  5.         // Inflate the window decor. 
  6.         //根據不同的features來選擇DecorView的布局 
  7.         int layoutResource; 
  8.         int features = getLocalFeatures(); 
  9.         // System.out.println("Features: 0x" + Integer.toHexString(features)); 
  10.         if ((features & (1 << FEATURE_SWIPE_TO_DISMISS)) != 0) { 
  11.             layoutResource = R.layout.screen_swipe_dismiss; 
  12.             setCloseOnSwipeEnabled(true); 
  13.         } else if ((features & ((1 << FEATURE_LEFT_ICON) | (1 << FEATURE_RIGHT_ICON))) != 0) { 
  14.             if (mIsFloating) { 
  15.                 TypedValue res = new TypedValue(); 
  16.                 getContext().getTheme().resolveAttribute( 
  17.                         R.attr.dialogTitleIconsDecorLayout, res, true); 
  18.                 layoutResource = res.resourceId; 
  19.             } else { 
  20.                 layoutResource = R.layout.screen_title_icons; 
  21.             } 
  22.             // XXX Remove this once action bar supports these features. 
  23.             removeFeature(FEATURE_ACTION_BAR); 
  24.             // System.out.println("Title Icons!"); 
  25.         } else if ((features & ((1 << FEATURE_PROGRESS) | (1 << FEATURE_INDETERMINATE_PROGRESS))) != 0 
  26.                 && (features & (1 << FEATURE_ACTION_BAR)) == 0) { 
  27.             // Special case for a window with only a progress bar (and title). 
  28.             // XXX Need to have a no-title version of embedded windows. 
  29.             layoutResource = R.layout.screen_progress; 
  30.             // System.out.println("Progress!"); 
  31.         } else if ((features & (1 << FEATURE_CUSTOM_TITLE)) != 0) { 
  32.             // Special case for a window with a custom title. 
  33.             // If the window is floating, we need a dialog layout 
  34.             if (mIsFloating) { 
  35.                 TypedValue res = new TypedValue(); 
  36.                 getContext().getTheme().resolveAttribute( 
  37.                         R.attr.dialogCustomTitleDecorLayout, res, true); 
  38.                 layoutResource = res.resourceId; 
  39.             } else { 
  40.                 layoutResource = R.layout.screen_custom_title; 
  41.             } 
  42.             // XXX Remove this once action bar supports these features. 
  43.             removeFeature(FEATURE_ACTION_BAR); 
  44.         } else if ((features & (1 << FEATURE_NO_TITLE)) == 0) { 
  45.             // If no other features and not embedded, only need a title. 
  46.             // If the window is floating, we need a dialog layout 
  47.             if (mIsFloating) { 
  48.                 TypedValue res = new TypedValue(); 
  49.                 getContext().getTheme().resolveAttribute( 
  50.                         R.attr.dialogTitleDecorLayout, res, true); 
  51.                 layoutResource = res.resourceId; 
  52.             } else if ((features & (1 << FEATURE_ACTION_BAR)) != 0) { 
  53.                 layoutResource = a.getResourceId( 
  54.                         R.styleable.Window_windowActionBarFullscreenDecorLayout, 
  55.                         R.layout.screen_action_bar); 
  56.             } else { 
  57.                 layoutResource = R.layout.screen_title; 
  58.             } 
  59.             // System.out.println("Title!"); 
  60.         } else if ((features & (1 << FEATURE_ACTION_MODE_OVERLAY)) != 0) { 
  61.             layoutResource = R.layout.screen_simple_overlay_action_mode; 
  62.         } else { 
  63.             // Embedded, so no decoration is needed. 
  64.             layoutResource = R.layout.screen_simple; 
  65.             // System.out.println("Simple!"); 
  66.         } 
  67.         mDecor.startChanging(); 
  68.         mDecor.onResourcesLoaded(mLayoutInflater, layoutResource); //挑選出來的布局添加到DecorView中 
  69.         ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT); //從DecorView找出id為com.android.internal.R.id.content的容器,提供給Activity使用。 
  70.         if (contentParent == null) { 
  71.             throw new RuntimeException("Window couldn't find content container view"); 
  72.         } 
  73.         ...... 
  74.         return contentParent; 
  75.     } 

R.layout.test

這一步純粹是為了看下DecorView布局文件長啥樣

  1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
  2.     android:layout_width="match_parent" 
  3.     android:layout_height="match_parent" 
  4.     android:fitsSystemWindows="true" 
  5.     android:orientation="vertical"
  6.     <ViewStub android:id="@+id/action_mode_bar_stub" 
  7.               android:inflatedId="@+id/action_mode_bar" 
  8.               android:layout="@layout/action_mode_bar" 
  9.               android:layout_width="match_parent" 
  10.               android:layout_height="wrap_content" 
  11.               android:theme="?attr/actionBarTheme" /> 
  12.     <!--真正存放Activity布局的容器--> 
  13.     <FrameLayout 
  14.          android:id="@android:id/content" 
  15.          android:layout_width="match_parent" 
  16.          android:layout_height="match_parent" 
  17.          android:foregroundInsidePadding="false" 
  18.          android:foregroundGravity="fill_horizontal|top" 
  19.          android:foreground="?android:attr/windowContentOverlay" /> 
  20. </LinearLayout> 

DecorView.onResourcesLoaded

  1. void onResourcesLoaded(LayoutInflater inflater, int layoutResource) { 
  2.        if (mBackdropFrameRenderer != null) { 
  3.            loadBackgroundDrawablesIfNeeded(); 
  4.            mBackdropFrameRenderer.onResourcesLoaded( 
  5.                    this, mResizingBackgroundDrawable, mCaptionBackgroundDrawable, 
  6.                    mUserCaptionBackgroundDrawable, getCurrentColor(mStatusColorViewState), 
  7.                    getCurrentColor(mNavigationColorViewState)); 
  8.        } 
  9.        mDecorCaptionView = createDecorCaptionView(inflater); 
  10.        final View root = inflater.inflate(layoutResource, null); //解析出布局文件 
  11.        if (mDecorCaptionView != null) { 
  12.            if (mDecorCaptionView.getParent() == null) { 
  13.                addView(mDecorCaptionView, 
  14.                        new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT)); 
  15.            } 
  16.            mDecorCaptionView.addView(root, 
  17.                    new ViewGroup.MarginLayoutParams(MATCH_PARENT, MATCH_PARENT)); 
  18.        } else { 
  19.            // Put it below the color views. 
  20.            addView(root, 0, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT)); //添加到DecorView 
  21.        } 
  22.        mContentRoot = (ViewGroup) root; //mContentRoot保存的是整個跟布局容器 
  23.        initializeElevation(); 
  24.    } 

 

二、DecorView繪制到屏幕

Activity 執行到 onCreate 時并不可見,只有執行完 onResume 之后 Activity 中的內容才是屏幕可見狀態。onCreate 階段只是初始化了 Activity 需要顯示的內容,而在 onResume 階段才會將 PhoneWindow 中的 DecorView 真正的繪制到屏幕上。

在ActivityThread的handleResumeActivity方法中,調用WindowManager將decor作為窗口添加到 WMS 。

  1. @Override 
  2.   public void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward, 
  3.           String reason) { 
  4.         ...... 
  5.         if (a.mVisibleFromClient) { 
  6.               if (!a.mWindowAdded) { 
  7.                   a.mWindowAdded = true
  8.                   wm.addView(decor, l); //通過WindowManager將decor添加到WMS 
  9.               } else { 
  10.                   // The activity will get a callback for this {@link LayoutParams} change 
  11.                   // earlier. However, at that time the decor will not be set (this is set 
  12.                   // in this method), so no action will be taken. This call ensures the 
  13.                   // callback occurs with the decor set
  14.                   a.onWindowAttributesChanged(l); 
  15.               } 
  16.           } 
  17.         ...... 

實現WindowManager接口的是WindowManagerImpl類,從WINDOW_SERVICE注冊時也能看出來。

  1. registerService(Context.WINDOW_SERVICE, WindowManager.class, new CachedServiceFetcher<WindowManager>() { 
  2.        @Override 
  3.        public WindowManager createService(ContextImpl ctx) { 
  4.            return new WindowManagerImpl(ctx); 
  5.        }}); 

WindowManagerImpl.addView調用mGlobal.addView方法,mGlobal是WindowManagerGlobal類型變量。

  1. @Override 
  2.    public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) { 
  3.        applyDefaultToken(params); 
  4.        mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow); 
  5.    } 

WindowManagerGlobal.addView最終調的是ViewRootImpl的setView方法

  1. public void addView(View view, ViewGroup.LayoutParams params, Display display, Window parentWindow) { 
  2.       ...... 
  3.       ViewRootImpl root; 
  4.       View panelParentView = null
  5.       synchronized (mLock) { 
  6.           ...... 
  7.           root = new ViewRootImpl(view.getContext(), display); //創建ViewRootImpl對象 
  8.           view.setLayoutParams(wparams); 
  9.           mViews.add(view); 
  10.           mRoots.add(root); 
  11.           mParams.add(wparams); 
  12.           // do this last because it fires off messages to start doing things 
  13.           try { 
  14.               root.setView(view, wparams, panelParentView); //最終,調的是ViewRootImpl的setView方法 
  15.           } catch (RuntimeException e) { 
  16.               // BadTokenException or InvalidDisplayException, clean up. 
  17.               if (index >= 0) { 
  18.                   removeViewLocked(indextrue); 
  19.               } 
  20.               throw e; 
  21.           } 
  22.       } 
  23.   } 

ViewRootImpl.setView

  1. public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) { 
  2.         synchronized (this) { 
  3.             if (mView == null) { 
  4.                 ...... 
  5.                 int res; /* = WindowManagerImpl.ADD_OKAY; */ 
  6.                 // Schedule the first layout -before- adding to the window 
  7.                 // manager, to make sure we do the relayout before receiving 
  8.                 // any other events from the system. 
  9.                 requestLayout(); //調用此方法后 ViewRootImpl 所關聯的 View 也執行 measure - layout - draw 操作,確保在 View 被添加到 Window 上顯示到屏幕之前,已經完成測量和繪制操作。 
  10.                 ...... 
  11.                 try { 
  12.                     mOrigWindowType = mWindowAttributes.type; 
  13.                     mAttachInfo.mRecomputeGlobalAttributes = true
  14.                     collectViewAttributes(); 
  15.                     // mWindowSession 的 addToDisplay 方法將 View 添加到 WMS 中。 
  16.                     res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes, 
  17.                             getHostVisibility(), mDisplay.getDisplayId(), mWinFrame, 
  18.                             mAttachInfo.mContentInsets, mAttachInfo.mStableInsets, 
  19.                             mAttachInfo.mOutsets, mAttachInfo.mDisplayCutout, mInputChannel); 
  20.                 } catch (RemoteException e) { 
  21.                     mAdded = false
  22.                     mView = null
  23.                     mAttachInfo.mRootView = null
  24.                     mInputChannel = null
  25.                     mFallbackEventHandler.setView(null); 
  26.                     unscheduleTraversals(); 
  27.                     setAccessibilityFocus(nullnull); 
  28.                     throw new RuntimeException("Adding window failed", e); 
  29.                 } finally { 
  30.                     if (restore) { 
  31.                         attrs.restore(); 
  32.                     } 
  33.                 } 
  34.             } 
  35.             ...... 
  36.         } 
  37.     } 

WindowSession實例獲取,是IWindowSession類型,通過Binder機制調用System 進程中的 Session實現。

  1. public static IWindowSession getWindowSession() { 
  2.       synchronized (WindowManagerGlobal.class) { 
  3.           if (sWindowSession == null) { 
  4.               try { 
  5.                   InputMethodManager imm = InputMethodManager.getInstance(); 
  6.                   IWindowManager windowManager = getWindowManagerService(); 
  7.                   sWindowSession = windowManager.openSession( 
  8.                           new IWindowSessionCallback.Stub() { 
  9.                               @Override 
  10.                               public void onAnimatorScaleChanged(float scale) { 
  11.                                   ValueAnimator.setDurationScale(scale); 
  12.                               } 
  13.                           }, 
  14.                           imm.getClient(), imm.getInputContext()); 
  15.               } catch (RemoteException e) { 
  16.                   throw e.rethrowFromSystemServer(); 
  17.               } 
  18.           } 
  19.           return sWindowSession; 
  20.       } 
  21.   } 

addToDisplay真正實現。

  1. @Override 
  2.   public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs, 
  3.           int viewVisibility, int displayId, Rect outFrame, Rect outContentInsets, 
  4.           Rect outStableInsets, Rect outOutsets, 
  5.           DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel, 
  6.           InsetsState outInsetsState) { 
  7.       return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId, outFrame, 
  8.               outContentInsets, outStableInsets, outOutsets, outDisplayCutout, outInputChannel, 
  9.               outInsetsState); 
  10.   } 

至此,Window 已經成功的被傳遞給了 WMS。剩下的工作就全部轉移到系統進程中的 WMS 來完成最終的添加操作。

三、觸摸事件處理

ViewRootImpl 中的 setView 方法中,除了調用 IWindowSession 執行跨進程添加 View 之外,還有一項重要的操作就是設置輸入事件的處理:

  1. public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) { 
  2.      ...... 
  3.      // Set up the input pipeline. 
  4.      CharSequence counterSuffix = attrs.getTitle(); 
  5.      mSyntheticInputStage = new SyntheticInputStage(); 
  6.      InputStage viewPostImeStage = new ViewPostImeInputStage(mSyntheticInputStage); 
  7.      InputStage nativePostImeStage = new NativePostImeInputStage(viewPostImeStage, 
  8.              "aq:native-post-ime:" + counterSuffix); 
  9.      InputStage earlyPostImeStage = new EarlyPostImeInputStage(nativePostImeStage); 
  10.      InputStage imeStage = new ImeInputStage(earlyPostImeStage, 
  11.              "aq:ime:" + counterSuffix); 
  12.      InputStage viewPreImeStage = new ViewPreImeInputStage(imeStage); 
  13.      InputStage nativePreImeStage = new NativePreImeInputStage(viewPreImeStage, 
  14.            "aq:native-pre-ime:" + counterSuffix); 
  15.      ...... 
  16.  } 

最終會經過ViewPostImeInputStage的onProcess處理

  1. final class ViewPostImeInputStage extends InputStage { 
  2.         public ViewPostImeInputStage(InputStage next) { 
  3.             super(next); 
  4.         } 
  5.         @Override 
  6.         protected int onProcess(QueuedInputEvent q) { 
  7.             if (q.mEvent instanceof KeyEvent) { 
  8.                 return processKeyEvent(q); 
  9.             } else { 
  10.                 final int source = q.mEvent.getSource(); 
  11.                 if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) { 
  12.                     return processPointerEvent(q); 
  13.                 } else if ((source & InputDevice.SOURCE_CLASS_TRACKBALL) != 0) { 
  14.                     return processTrackballEvent(q); 
  15.                 } else { 
  16.                     return processGenericMotionEvent(q); 
  17.                 } 
  18.             } 
  19.         } 

processPointerEvent方法,調用mView的dispatchPointerEvent 分發事件。mView是DecorView對象

  1. private int processPointerEvent(QueuedInputEvent q) { 
  2.            ...... 
  3.            boolean handled = mView.dispatchPointerEvent(event); 
  4.            ...... 
  5.            return handled ? FINISH_HANDLED : FORWARD
  6.        } 

dispatchPointerEvent是View實現的,最終調的是dispatchTouchEvent方法。

  1. public final boolean dispatchPointerEvent(MotionEvent event) { 
  2.        if (event.isTouchEvent()) { 
  3.            return dispatchTouchEvent(event); 
  4.        } else { 
  5.            return dispatchGenericMotionEvent(event); 
  6.        } 
  7.    } 

DecorView.dispatchTouchEvent最終調用PhoneWindow的Callback分發事件。

  1. @Override 
  2.    public boolean dispatchTouchEvent(MotionEvent ev) { 
  3.        final Window.Callback cb = mWindow.getCallback(); 
  4.        return cb != null && !mWindow.isDestroyed() && mFeatureId < 0 
  5.                ? cb.dispatchTouchEvent(ev) : super.dispatchTouchEvent(ev); 
  6.    } 

PhoneWindow的Callback是在Activity的attach時設置的

  1. final void attach(Context context, ActivityThread aThread, 
  2.            Instrumentation instr, IBinder token, int ident, 
  3.            Application application, Intent intent, ActivityInfo info, 
  4.            CharSequence title, Activity parent, String id, 
  5.            NonConfigurationInstances lastNonConfigurationInstances, 
  6.            Configuration config, String referrer, IVoiceInteractor voiceInteractor, 
  7.            Window window, ActivityConfigCallback activityConfigCallback) { 
  8.        attachBaseContext(context); 
  9.        mFragments.attachHost(null /*parent*/); 
  10.        mWindow = new PhoneWindow(this, window, activityConfigCallback); 
  11.        mWindow.setWindowControllerCallback(this); 
  12.        mWindow.setCallback(this); //將Activity對象傳遞給PhoneWindow 
  13.        ...... 
  14.    } 

下面就回到了我們熟悉的Activity的dispatchTouchEvent方法:

  1. public boolean dispatchTouchEvent(MotionEvent ev) { 
  2.        if (ev.getAction() == MotionEvent.ACTION_DOWN) { 
  3.            onUserInteraction(); 
  4.        } 
  5.        if (getWindow().superDispatchTouchEvent(ev)) { //調用PhoneWindow的superDispatchTouchEvent方法 
  6.            return true
  7.        } 
  8.        return onTouchEvent(ev); 
  9.    } 

PhoneWindow.superDispatchTouchEvent,歸根結底還是調的DecorView的superDispatchTouchEvent方法

  1. @Override 
  2.   public boolean superDispatchTouchEvent(MotionEvent event) { 
  3.       return mDecor.superDispatchTouchEvent(event); 
  4.   } 

DecorView.superDispatchTouchEvent,調用ViewGroup的dispatchTouchEvent方法。

  1. public boolean superDispatchTouchEvent(MotionEvent event) { 
  2.        return super.dispatchTouchEvent(event); 
  3.    } 

總結

1.整個過程Activity參與度很低,基本靠PhoneWindow實現。

2.onCreate階段創建了DecorView,onResume階段將DecorView添加到WMS并展示,ViewRootImple對象也是onResume階段創建的,所以也解釋了onCreate階段子線程加載view并不會報錯。

3.ViewRootImpl 的 setView 方法中主要完成兩件事情:View 渲染(requestLayout)以及接收觸屏事件。

4.一個 Activity 中有一個 window,也就是 PhoneWindow 對象,每一個 PhoneWindow 對應一個 ViewRootImple 對象。

本文轉載自微信公眾號「Android開發編程」

 

責任編輯:姜華 來源: Android開發編程
相關推薦

2021-08-10 20:41:33

AndroidApp流程

2021-08-11 17:15:17

AndroidActivity場景

2021-09-02 07:00:01

Glide流程Android

2021-09-29 09:42:32

AndroidViewDragHel拖動上下滑卡片

2021-08-25 07:43:17

AndroidSurfaceViewTextureView

2021-09-14 07:06:12

Android磁盤緩存

2021-08-24 07:53:28

AndroidActivity生命周期

2021-09-07 06:40:25

AndroidLiveData原理

2015-07-28 17:11:00

編程技術提升

2021-09-01 06:48:16

AndroidGlide緩存

2021-10-03 15:08:32

Android

2021-08-17 13:41:11

AndroidView事件

2014-07-15 17:17:31

AdapterAndroid

2021-07-14 14:27:01

AndroidAOPhugo

2023-11-15 08:28:13

PythonVTK

2014-05-27 15:36:01

AndroidActivity啟動模式

2021-09-17 06:55:50

AndroidLayoutView

2021-09-16 06:44:04

Android進階流程

2021-09-03 07:27:38

AndroidGlide管理

2021-08-09 20:29:27

Android沉浸式狀態欄
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产精品成av人在线视午夜片 | 久久亚洲综合 | 亚洲福利电影网 | 日本一二区视频 | 日韩电影在线一区 | 国产在线精品一区 | 国产综合精品 | 久久99精品久久久久 | 国产精品中文字幕在线观看 | 久久精品国产亚洲a | 亚洲网站在线观看 | 国产精品亚洲一区二区三区在线 | 一区二区在线不卡 | 黄色一级大片在线免费看产 | 99这里只有精品视频 | h视频在线免费 | 国产精品亚洲精品久久 | 天天射影院 | 日韩成年人视频在线 | 免费激情av | 久久精品亚洲精品国产欧美 | 欧美a v在线 | 国产高清在线精品 | 久久免费小视频 | 国产精品久久毛片av大全日韩 | 久久久久久久久久久久久9999 | 亚洲视频免费播放 | 免费激情 | 欧美国产精品 | 自拍偷拍精品 | 91在线精品视频 | 亚洲精品成人在线 | 99久久99| 日韩不卡三区 | 欧美一区免费 | 91网视频| 亚洲黄色av | 亚洲欧洲成人av每日更新 | 日韩精品视频在线 | 性生活毛片| 国产在线观看一区二区 |