国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

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

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

[[418895]]

前言

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

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

一、DecorView的創(chuàng)建

Activity.setContentView

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

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

(PhoneWindow是Window的唯一實現(xiàn)類)

  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

幾個關(guān)鍵變量

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為空,則執(zhí)行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); //如果之前沒有創(chuàng)建,直接創(chuàng)建一個 
  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()); //創(chuàng)建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.         //根據(jù)不同的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 執(zhí)行到 onCreate 時并不可見,只有執(zhí)行完 onResume 之后 Activity 中的內(nèi)容才是屏幕可見狀態(tài)。onCreate 階段只是初始化了 Activity 需要顯示的內(nèi)容,而在 onResume 階段才會將 PhoneWindow 中的 DecorView 真正的繪制到屏幕上。

在ActivityThread的handleResumeActivity方法中,調(diào)用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.         ...... 

實現(xiàn)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調(diào)用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最終調(diào)的是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); //創(chuàng)建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); //最終,調(diào)的是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(); //調(diào)用此方法后 ViewRootImpl 所關(guān)聯(lián)的 View 也執(zhí)行 measure - layout - draw 操作,確保在 View 被添加到 Window 上顯示到屏幕之前,已經(jīng)完成測量和繪制操作。 
  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機制調(diào)用System 進程中的 Session實現(xiàn)。

  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真正實現(xiàn)。

  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 已經(jīng)成功的被傳遞給了 WMS。剩下的工作就全部轉(zhuǎn)移到系統(tǒng)進程中的 WMS 來完成最終的添加操作。

三、觸摸事件處理

ViewRootImpl 中的 setView 方法中,除了調(diào)用 IWindowSession 執(zhí)行跨進程添加 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.  } 

最終會經(jīng)過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方法,調(diào)用mView的dispatchPointerEvent 分發(fā)事件。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實現(xiàn)的,最終調(diào)的是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最終調(diào)用PhoneWindow的Callback分發(fā)事件。

  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)) { //調(diào)用PhoneWindow的superDispatchTouchEvent方法 
  6.            return true
  7.        } 
  8.        return onTouchEvent(ev); 
  9.    } 

PhoneWindow.superDispatchTouchEvent,歸根結(jié)底還是調(diào)的DecorView的superDispatchTouchEvent方法

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

DecorView.superDispatchTouchEvent,調(diào)用ViewGroup的dispatchTouchEvent方法。

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

總結(jié)

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

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

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

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

本文轉(zhuǎn)載自微信公眾號「Android開發(fā)編程」

 

責任編輯:姜華 來源: Android開發(fā)編程
相關(guān)推薦

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

編程技術(shù)提升

2021-10-03 15:08:32

Android

2021-09-01 06:48:16

AndroidGlide緩存

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性能優(yōu)化渲染

2021-09-03 07:27:38

AndroidGlide管理
點贊
收藏

51CTO技術(shù)棧公眾號

国产精品一区二区三区免费| 日本美女高清在线观看免费| 黄色成人精品网站| 欧美片一区二区三区| 电影在线观看一区| 日韩午夜小视频| 国产女人在线观看| 天天综合天天综合色| 黄大色黄女片18第一次| 久久综合999| 亚洲 自拍 另类小说综合图区| 久久精品99久久久| 视频二区一区| 九九九久久久精品| 艳母动漫在线免费观看| 久久精品久久综合| 一本二本三本亚洲码| 久久激五月天综合精品| 亚洲一区二区免费视频软件合集| 久久久久.com| 日韩精品另类天天更新| 久久不射中文字幕| 久久精品国产一区二区三区日韩| 亚洲看片免费| 日韩精品一区二区三区丰满| 噜噜噜91成人网| 亚洲精品一区二区三| 激情久久五月天| 日韩 欧美 自拍| 国产精品一区二区无线| 成年女人18级毛片毛片免费| 国产精品12区| 国产中文字幕视频在线观看| 国产精品久久久爽爽爽麻豆色哟哟 | 欧美日韩视频| 国产精品一区免费观看| 日本大胆欧美人术艺术动态| 天堂v在线视频| 久久久99精品久久| 黄页免费在线| 欧美日韩一区中文字幕| 亚洲美女炮图| 97视频在线观看亚洲| 色狮一区二区三区四区视频| 精品毛片久久久久久| 国产另类ts人妖一区二区| 成人亚洲视频在线观看| 亚洲制服欧美中文字幕中文字幕| 大片免费播放在线视频| 日韩成人在线观看| 91欧美极品| 99久久伊人精品影院| 久久香蕉精品| 波多野结衣50连登视频| 亚洲五码中文字幕| 在线电影福利片| 欧美精品www在线观看| 欧美午夜在线| 国产a级一级片| 欧洲一区二区三区在线| 免费成人黄色网| 91亚洲va在线va天堂va国| 国产一区二区在线观看视频| 美女免费免费看网站| 精品av久久707| 乱中年女人伦av一区二区| 久久免费视频1| 欧美国产日韩精品免费观看| 一级毛片视频在线| 国内久久久精品| 亚洲韩日在线| 久久久久久久久久久久久国产精品| 黄网动漫久久久| 成人在线免费av| 精品国产乱码久久久久久88av| 99r国产精品| 欧美高清视频| 国产成人久久久| 国产不卡免费视频| 国产福利小视频在线观看| 久久中文字幕国产| 久久av一区| 在线中文字幕观看| 欧美精品做受xxx性少妇| 久久一区中文字幕| 中出福利视频| 久久精品国产69国产精品亚洲| 欧美日韩国产综合网| 精品视频无码一区二区三区| 91精品国产乱| 久久蜜桃av| 91福利国产成人精品播放| 日韩精品视频免费| 欧美精品午夜| 色av一区二区三区| 久久久国产精彩视频美女艺术照福利 | 日本免费高清一区二区| 亚洲免费在线视频| 日韩福利影视| 日韩高清国产一区在线观看| 亚洲国产日韩a在线播放性色| 日本肉肉一区| 亚洲 日韩 国产第一区| 欧美日韩免费区域视频在线观看| 亚洲成人五区| 黄页网站大全在线观看| 精品国产伦一区二区三区免费| 亚洲精品888| 黄页大全在线免费观看| 26uuu亚洲国产精品| 91色在线porny| 免费污视频在线一区| 一区二区三区四区欧美日韩| 欧美日韩一区二区三区四区| 91嫩草亚洲精品| 99热免费观看| 久久99国产综合精品女同| 国产成人精品免费一区二区| 美女的胸无遮挡在线观看| 日韩欧美手机在线| 日韩精品一区二区三区在线播放| 伊人成年综合电影网| 精品久久av| 国产精品视频免费一区二区三区| 久久三级毛片| 日韩片之四级片| 欧美精品第1页| 91在线丨porny丨国产| 正在播放日韩精品| 黄色成人av网站| 一区二区三区毛片免费| 雨宫琴音一区二区三区| 中文字幕一区二区三区中文字幕| 一级日韩一区在线观看| 91精品国产91久久久久福利| 国产精品久久看| 91麻豆产精品久久久久久 | 日韩一中文字幕| 国产精品露脸自拍| 99久久综合狠狠综合久久止| 国内精品模特av私拍在线观看| 欧美夫妻性生活视频| av在线不卡一区| 波多野结衣精品久久| 亚洲国产欧美自拍| 欧美一级免费视频| 国产精品一区二区三区在线播放| 日韩视频永久免费观看| 亚洲国产精品网站| 日韩天堂在线观看| 亚洲精品免费播放| 亚洲精品国产无天堂网2021| 国产精品入口麻豆九色| heyzo一本久久综合| 成人黄色av| 欧美激情偷拍| 欧美日韩一卡| 日韩精品欧美成人高清一区二区| 亚洲欧美不卡| 国产一区二区三区四区五区入口| 日韩激情一二三区| 久久久久久久欧美精品| 色综合久久影院| 6080成人| 日韩夫妻性生活xx| bbbbbbbbbbb在线视频| 在线成人av观看| 四虎av网址| 欧美日产国产成人免费图片| 中文字幕av一区二区三区| 日韩久久电影| 2024最新电影在线免费观看| 国产欧美日韩小视频| 国产91精品在线播放| 欧美人妇做爰xxxⅹ性高电影| 看电视剧不卡顿的网站| 91夜夜蜜桃臀一区二区三区| 久色视频在线| 无码人妻少妇伦在线电影| 69av在线播放| 制服丝袜av成人在线看| 91亚洲男人天堂| 亚洲女同中文字幕| 四虎4545www精品视频| 免费三级欧美电影| 天天综合色天天综合色hd| 九九热这里只有在线精品视| 色婷婷综合中文久久一本| 国产一区 二区 三区一级| 欧美日韩激情在线一区二区三区| 97人人爽人人澡人人精品| 黑粗硬长欧美在线视频免费的| 日韩欧美一区二区在线观看 | 91麻豆国产自产在线观看亚洲| bl在线肉h视频大尺度| 人成在线视频| 精品无码国产一区二区三区av| 91偷拍精品一区二区三区| 久热爱精品视频线路一| 这里是久久伊人|