精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

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-09-07 06:40:25

AndroidLiveData原理

2021-08-24 07:53:28

AndroidActivity生命周期

2015-07-28 17:11:00

編程技術提升

2021-09-01 06:48:16

AndroidGlide緩存

2021-10-03 15:08:32

Android

2021-07-14 14:27:01

AndroidAOPhugo

2014-07-15 17:17:31

AdapterAndroid

2021-08-17 13:41:11

AndroidView事件

2014-05-27 15:36:01

AndroidActivity啟動模式

2023-11-15 08:28:13

PythonVTK

2021-09-16 06:44:04

Android進階流程

2021-09-17 06:55:50

AndroidLayoutView

2015-09-16 13:54:30

Android性能優化渲染

2021-08-09 20:29:27

Android沉浸式狀態欄
點贊
收藏

51CTO技術棧公眾號

蜜桃精品视频在线| 99久久久国产精品美女| 色欧美片视频在线观看| 亚洲精蜜桃久在线| 99久久久国产精品无码免费| 亚洲国内自拍| 日韩在线视频导航| a级一a一级在线观看| 国产精品66| 精品毛片网大全| 一个色的综合| 亚洲 另类 春色 国产| 国产在线国偷精品免费看| 4388成人网| 欧美成人黄色网| 成人在线免费小视频| 欧美大片日本大片免费观看| 亚洲狼人综合干| 欧洲一区二区三区| 国产精品久久久久久久久久免费看 | 日本中文字幕一区二区有限公司| 欧美国产日韩中文字幕在线| 伊人影院综合网| 日本午夜精品| 亚洲第一色中文字幕| 亚洲精品成人在线播放| 欧美日韩美女| 精品国产福利视频| 免费网站在线观看视频| 欧美jizzhd欧美| 国产精品视频免费| 日本成人三级| 色综合888| 97久久超碰精品国产| 高清av免费一区中文字幕| 国产精品成人久久久| 麻豆91精品| 91av视频导航| 日韩乱码在线观看| 在线精品观看| 欧美激情精品久久久久久黑人| 老熟妇高潮一区二区三区| 精品国产中文字幕第一页| 亚洲欧美制服第一页| 久久国产精品影院| 嫩草影视亚洲| 亚洲视频在线观看| 亚洲综合网在线观看| 天堂在线精品| 亚洲午夜精品久久久久久久久久久久 | 四虎永久免费网站| 成人影院在线观看| 亚洲欧美另类图片小说| 日韩一级特黄毛片| 阿v视频在线| 疯狂做受xxxx欧美肥白少妇| av天堂永久资源网| 欧美香蕉视频| 欧美色手机在线观看| 久久婷五月综合| 亚洲国产一区二区久久| 777欧美精品| 日韩高清一二三区| 欧美成人基地| 亚洲一区av在线播放| 黑人と日本人の交わりビデオ| 色999日韩| 久久成人国产精品| 国产乡下妇女做爰视频| 欧美亚洲一级| 成人妇女淫片aaaa视频| 午夜精品在线播放| 99国产精品国产精品毛片| 蜜桃成人在线| 日韩子在线观看| 亚洲制服丝袜在线| 成人一级片网站| 四虎影视国产精品| 欧美r级在线观看| 蜜臀av一区二区三区有限公司| 国产精品一区二区三区av麻| 久久视频精品在线| 国产精品7777777| 老**午夜毛片一区二区三区| 国产欧美日韩中文| 二区三区在线视频| 久久综合五月天婷婷伊人| 欧美日韩成人一区二区三区 | 99热手机在线| 精品国产鲁一鲁****| 日韩电影中文字幕在线| 女教师淫辱の教室蜜臀av软件| 欧美午夜在线视频| 国产精品高清在线观看| 亚洲黄色a级片| 久久久91精品国产一区二区三区| 色撸撸在线观看| 在线观看涩涩| 日韩一区二区三区高清免费看看| 男生裸体视频网站| 91精品蜜臀一区二区三区在线| 97视频在线看| a天堂在线观看视频| 久久亚洲私人国产精品va媚药| 伊人久久大香线蕉成人综合网| 少妇视频一区| 欧美一级日韩一级| 欧美成人短视频| 久久av一区| 国产美女精品久久久| 日本视频不卡| 日本韩国一区二区三区| 国产免费一区二区三区最新6| 久久婷婷蜜乳一本欲蜜臀| 97在线视频精品| 精品毛片一区二区三区| 国产精品三级在线观看| 99爱视频在线| 99久久香蕉| 久久91亚洲精品中文字幕| 做爰视频毛片视频| 91蜜桃传媒精品久久久一区二区| a级黄色片免费| 亚洲精品aaa| 色av中文字幕一区| 波多野结衣一区二区在线 | 欧美一区二区精品在线| 久操视频在线观看免费| 亚洲综合日韩| 精品国产乱码久久久久软件| 亚洲精品白浆| 欧美一区二区三区的| 成人免费视频网站入口::| 久久er99精品| 在线一区日本视频| 成人亚洲精品| 久久久精品一区| 国产精品久久久久久久久久久久久久久久| 久久久久国产一区二区三区四区| 18禁免费观看网站| 女一区二区三区| 97视频色精品| 天堂91在线| 欧美性猛交xxxx富婆弯腰| 天堂久久久久久| 性欧美暴力猛交另类hd| 热re99久久精品国产99热| 欧美日韩美女| 自拍偷拍亚洲在线| 亚洲一卡二卡在线观看| 中文字幕在线观看不卡| 九九热免费在线观看| 91精品国产自产拍在线观看蜜 | 国产精品拍拍拍| 欧美限制电影| 91麻豆国产语对白在线观看| 久久这里只精品| 一级黄色片免费看| 日本一区二区视频在线| 欧美午夜性生活| 欧美日韩第一| 成人精品久久av网站| 操你啦视频在线| 欧美成人女星排名| 日操夜操天天操| 久久久综合网站| 蜜臀av免费观看| 中文不卡在线| 国产精品一区二区三区四区五区| 国产福利片在线观看| 精品视频久久久久久久| 国产精品无码粉嫩小泬| 亚洲欧美日韩综合aⅴ视频| 欧美人与性动交α欧美精品| 99精品福利视频| 日韩精品欧美在线| 国产精品一区三区在线观看| 久久久久国产精品免费| 天堂影院在线| 欧美二区三区的天堂| 国产一级片免费观看| 久久久久久久久久看片| 亚洲精品乱码久久久久久动漫| 亚洲高清自拍| 亚洲v国产v| 黑人久久a级毛片免费观看| 日本成人免费在线| 成人三级网址| 亚洲免费视频一区二区| 国产精品一区二区人人爽| 午夜久久电影网| 永久免费未视频| 久久久午夜精品理论片中文字幕| 中文字幕亚洲影院| 国产午夜久久| 日本女人高潮视频| 国产欧美高清视频在线| 国产久一道中文一区| 国产亚洲欧美日韩精品一区二区三区 | 激情久久久久| 一区二区三区四区国产| 日韩av三区| 亚洲淫片在线视频| 欧美影视资讯| 午夜精品福利在线观看| 国产午夜精品久久久久免费视| 亚洲免费av网址| 国产香蕉在线观看| 在线观看91av| 波多野结衣一区二区三区在线 | 久久久精品久久| 六十路在线观看| 精品国产电影一区二区| 91精品国产色综合久久不8| 精品久久中文字幕| 久久一区二区三| 中文字幕一区二区在线播放 | 丰满人妻一区二区| 欧美日韩激情一区二区| aaa在线视频| 午夜视频一区二区| 国产精品30p| 亚洲免费观看高清完整版在线观看熊| 一二三四国产精品| 国产视频一区在线播放| 久久久久国产精品区片区无码| 国产成人丝袜美腿| 91插插插影院| 久久国产精品第一页| 亚洲精品一二三四五区| 久久经典综合| 99精品免费在线观看| 国产女优一区| 欧美三级一级片| 99视频精品| 缅甸午夜性猛交xxxx| 亚洲天堂男人| 欧美性潮喷xxxxx免费视频看| 欧美粗暴jizz性欧美20| 强开小嫩苞一区二区三区网站| 91精品综合久久久久久久久久久| 亚洲国产精品久久久久婷婷老年 | 成人小视频免费观看| 亚洲国产综合av| 国产福利一区在线观看| 白丝校花扒腿让我c| 国产精品18久久久久| av地址在线观看| 粉嫩高潮美女一区二区三区 | 中文无字幕一区二区三区 | 欧美在线a视频| 国产美女久久久久| 波多野结衣电影免费观看| 高清在线不卡av| 日本人妻一区二区三区| 99精品欧美一区二区三区小说 | 色视频在线观看福利| 精品中文视频在线| 国产福利免费在线观看| 日韩中文字幕免费看| а√资源新版在线天堂| 欧美激情精品久久久久久大尺度| heyzo高清在线| 日韩美女中文字幕| 日韩美女在线| 成人av资源| 亚洲另类春色校园小说| 午夜精品电影在线观看| 性欧美69xoxoxoxo| 免费不卡av在线| 久久亚洲影院| 欧美又黄又嫩大片a级| 丁香六月久久综合狠狠色| www.超碰97| 国产精品激情偷乱一区二区∴| 日韩成人毛片视频| 欧美日韩午夜剧场| 伊人网站在线观看| 精品国产一区二区在线观看| 日韩美女一级视频| 日韩日本欧美亚洲| 操喷在线视频| 国产精品久久久久久久久久久久 | 国产成人免费av在线| 亚洲AV无码国产精品| 国产精品日韩成人| 国产精品第二十页| 欧美网站大全在线观看| 亚洲国产综合一区| 一本色道久久88综合亚洲精品ⅰ | 国产精品久久久久77777| 高清久久一区| 欧美系列一区| 亚洲欧美综合国产精品一区| 国产1区2区在线| 国产精品88av| jizz18女人高潮| 亚洲一区二区三区四区在线 | 麻豆91精品91久久久的内涵| av av在线| 亚洲视频香蕉人妖| 久久久蜜桃一区二区| 亚洲第一av在线| 蜜桃av在线免费观看| 日本免费久久高清视频| 91麻豆精品激情在线观看最新 | 亚洲婷婷在线| 不用播放器的免费av| 久久久久久日产精品| 国产第100页| 欧美一区二区在线播放| 美女做暖暖视频免费在线观看全部网址91| 久久这里只有精品视频首页| 欧美二三四区| 国产伦精品一区二区三区照片| 久久久久久美女精品| 午夜国产一区二区三区| 久久精品国产亚洲5555| av不卡在线播放| www.国产福利| 久久久精品黄色| 国产亚洲精品女人久久久久久| 欧美日韩午夜精品| 你懂的视频在线| 欧美激情视频一区二区| 台湾天天综合人成在线| 青青成人在线| 久久xxxx| 亚洲一区二区三区综合| 日韩va亚洲va欧美va久久| 91精品国产色综合久久ai换脸| yjizz国产| 精品久久久久久久久久久久包黑料| 77导航福利在线| 国产精品成人久久久久| 久久综合色占| 欧美国产日韩在线播放| 久久久高清一区二区三区| 色网站在线播放| 精品无人区乱码1区2区3区在线| 麻豆av在线播放| 9a蜜桃久久久久久免费| 国产黄大片在线观看画质优化| 日韩电影免费在线看| 国产黄色特级片| 久久一日本道色综合| 九九热在线免费观看| 日韩精品视频在线| 午夜影院在线播放| 欧美国产一区二区在线| 久久激情久久| 成人小视频免费看| 欧美久久久久久久久| 黄色精品免费看| 97se国产在线视频| 亚洲激情自拍| 大尺度在线观看| 婷婷综合在线观看| 理论视频在线| 91精品久久久久久久久久久| 久久久久久影院| 深夜视频在线观看| 精品久久久视频| av中文字幕在线| 91久久国产综合久久91精品网站| 亚洲蜜桃视频| 欧美丰满熟妇bbb久久久| 婷婷综合另类小说色区| 黄色在线播放| 91精品久久久久久久久不口人| 欧美va天堂在线| 少妇户外露出[11p]| 欧美性xxxxx极品少妇| 国产高清一区二区三区视频| 国产高清自拍一区| 久久天堂精品| 日韩视频中文字幕在线观看| 日韩成人中文字幕在线观看| 视频一区在线免费看| 日本免费黄色小视频| 91香蕉视频mp4| 91丨porny丨在线中文 | 免费亚洲电影在线| 全网免费在线播放视频入口 | 欧美午夜不卡影院在线观看完整版免费| 中文字幕在线视频播放| 欧美日韩午夜影院| av资源中文在线天堂| 午夜一区二区三区| 国产成人综合网| 国产九色91回来了| 久久免费视频这里只有精品| 日韩大片在线| 日韩av手机在线播放| 91麻豆精品国产91久久久久久| 波多野结衣精品| 国产高清免费在线| 91丨国产丨九色丨pron| www.av导航| 国产日韩欧美在线|