ViewRootImpl源码解读

主要功能

消息传递

1
2
3
4
5
6
7
8
9
10
11
12
13
前置消息生成
hardWare&nativeCode ->

InputEventReceiver(dispatchInputEvent)->

ViewRootImpl$WindowInputEventReceiver(dispatchInputEvent)->

ViewRootImpl(enqueueInputEvent) ->

if processImmediately
ViewRootImpl(doProcessInputEvents)
else
ViewRootImpl(scheduleProcessInputEvents)

KeyEvent

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Target:to find the focus one self or child.

get from QueuedInputEvent .....->

ViewRootImpl$ViewPostImeInputStage(onProcess)->

ViewRootImpl$ViewPostImeInputStage(processKeyEvent)->

PhoneWindow$DecorView(dispatchKeyEvent)->

Activity implenments Windows.CallBack(dispathcKeyEvent) ->

PhoneWindow$DecorView(superDispatchKeyEvent) ->

ViewGroup(dispatchKeyEvent) ->

View(dispatchKeyEvent) ->

KeyEvent(dispatch)
ViewGroup:dispatchKeyEvent
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
 

@Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (mInputEventConsistencyVerifier != null) {
mInputEventConsistencyVerifier.onKeyEvent(event, 1);
}

//##important:here decide parent first and then child
//## to find the focus one
if ((mPrivateFlags & (PFLAG_FOCUSED | PFLAG_HAS_BOUNDS))
== (PFLAG_FOCUSED | PFLAG_HAS_BOUNDS)) {
if (super.dispatchKeyEvent(event)) {
return true;
}
} else if (mFocused != null && (mFocused.mPrivateFlags & PFLAG_HAS_BOUNDS)
== PFLAG_HAS_BOUNDS) {
if (mFocused.dispatchKeyEvent(event)) {
return true;
}
}

if (mInputEventConsistencyVerifier != null) {
mInputEventConsistencyVerifier.onUnhandledEvent(event, 1);
}
return false;
}
View:dispatchKeyEvent
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/**
* Dispatch a key event to the next view on the focus path. This path runs
* from the top of the view tree down to the currently focused view. If this
* view has focus, it will dispatch to itself. Otherwise it will dispatch
* the next node down the focus path. This method also fires any key
* listeners.
*
* @param event The key event to be dispatched.
* @return True if the event was handled, false otherwise.
*/
public boolean dispatchKeyEvent(KeyEvent event) {
if (mInputEventConsistencyVerifier != null) {
mInputEventConsistencyVerifier.onKeyEvent(event, 0);
}

// Give any attached key listener a first crack at the event.
//noinspection SimplifiableIfStatement
// setOnKeyListener
ListenerInfo li = mListenerInfo;
if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
&& li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
return true;
}

if (event.dispatch(this, mAttachInfo != null
? mAttachInfo.mKeyDispatchState : null, this)) {
return true;
}

if (mInputEventConsistencyVerifier != null) {
mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
}
return false;
}
Activity:dispatchKeyEvent
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/**
* Called to process key events. You can override this to intercept all
* key events before they are dispatched to the window. Be sure to call
* this implementation for key events that should be handled normally.
*
* @param event The key event.
*
* @return boolean Return true if this event was consumed.
*/
public boolean dispatchKeyEvent(KeyEvent event) {
onUserInteraction();

// Let action bars open menus in response to the menu key prioritized over
// the window handling it
if (event.getKeyCode() == KeyEvent.KEYCODE_MENU &&
mActionBar != null && mActionBar.onMenuKeyEvent(event)) {
return true;
}

//##important:here decide the sequece ViewGroup View Activity;
Window win = getWindow();
if (win.superDispatchKeyEvent(event)) {
return true;
}
View decor = mDecor;
if (decor == null) decor = win.getDecorView();
// at last
return event.dispatch(this, decor != null
? decor.getKeyDispatcherState() : null, this);
}

TouchEvent

1
2
3
4
5
6
7
8
9
10
11
Sequence:dispatchTouchEvent,onInterceptTouchEvent,onTouchEvent ,U型传递

get from QueueInputEvent....->
ViewRootImpl$ViewPostImeInputStage(processPointerEvent)->
View(dispatchPointerEvent)->
PhoneWindow$DecorView(dispatchTouchEvent)->
Activity implements Windows.CallBack:(dispatchTouchEvent)->
PhoneWindow$DecorView(superDispatchTouchEvent)->
ViewGroup(dispatchTouchEvent)->
View(dispatchTouchEvent)->
.........
U型传递图

ViewRootImpl_U1

总结:

  1. touch事件先子View后父View,key事件先父View后子View,Activity作为兜底方案
  2. 不论是touch事件还是key事件都是自顶向下分发的
  3. …….

与windowsManagerService通信

IWindowSession

1
2
3
4
new ViewRootImpl ->
WindowManagerGlobal(getWindowSession)->
WindowManagerService(openSession) ->
......
Session

This class represents an active client session. There is generally one Session object per process that is interacting with the window manager.

1
2
3
4
5
6
7
8
9
10

//## from WindowManagerService openSession
@Override
public IWindowSession openSession(IWindowSessionCallback callback, IInputMethodClient client,
IInputContext inputContext) {
if (client == null) throw new IllegalArgumentException("null client");
if (inputContext == null) throw new IllegalArgumentException("null inputContext");
Session session = new Session(this, callback, client, inputContext);
return session;
}

SurfaceSession

How to Create
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
ActivityThread(handleResumeActivity) ->

WindowManagerGlobal(addView)->

ViewRootImpl(setView) ->

Session(addToDisplay)->

WindowManagerService(addWindow) ->

WindowState(attach) ->

Session(windowAddedLocked)->

new SurfaceSession

触发视图的更新

Activity的onCreate

1
2
3
4
5
6
7
ActivityThread(handleLaunchActivity) -> 

ActivityThread performLaunchActivity ->

Instrumentation(callActivityOnCreate) ->

Activity(onCreate)

DecorView的建立

via setContentView

1
2
3
4
5
6
7
8
9
Activity (setContentView)->

PhoneWindow(setContentView)->

PhoneWindow(installDecor)->

PhoneWindow(generateDecor)->

new DecorView -> LayoutInflater .......

DecorView的添加

via onResume

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//## Surface create in ViewRootImpl but is Empty
//## surface filled data in outSurface.copyFrom(surfaceControl)

ActivityThread (handleResumeActivity) ->

WindowManagerGlobal(addView)->

ViewRootImpl(setView)->

......

ViewRootImpl(performTraversals)->

ViewRootImpl(relayoutWindow)->

Session(relayout)->

WindowManagerService(relayoutWindow)->

WindowStateAnimator createSurfaceLocked outSurface.copyFrom(surfaceControl)->.....

AttachToWindow

1
2
3
4
5
6
7
8
9
10
11
12
ActivityThread(handleResumeActivity)->

WindowManagerGlobal(addView)->

ViewRootImpl(setView)->

ViewRootImpl(requestLayout) ......->

ViewRootImpl(performTraversals)
[here host.dispatchAttachedToWindow ,host.dispatchWindowVisibilityChanged ......onMeasure ,onLayout,onDraw....]->

......

DettachToWindow

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
ActivityThread(handleDestroyActivity)->

WindowManagerImpl(removeViewImmediate)->

WindowManagerGlobal(removeView)->

WindowManagerGlobal(removeViewLocked)->

ViewRootImpl(die)->

ViewRootImpl(doDie)->

ViewRootImpl(dispatchDetachedFromWindow)->

View(dispatchDetachedFromWindow)->

......

其他

数据生命周期

attachInfo

1
2
3
4
5
6
7
8
9
10
11
12
//##ViewRootImpl
//Create
new ViewRootImpl->

new View.AttachInfo(mWindowSession, mWindow, display, this, mHandler, this)


//dispatch to children
dispatchAttachedToWindow

//destory
dispatchDetachedFromWindow[attachinfo=null]

viewParent

1
2
3
4
5
6
7
//##ViewRootImpl

//dispatch to children on dispatchAttachToWindow
assignParent(this)

//detory on dispatchDetachFromWindow
assignParent(null)