前言
前前后后经历过大项目、小项目,跨平台,小程序,Nodejs服务等等,目前在做的Rom开发,定制各种手机中的奇葩需求,从应用层到Framework层,再到C++层,再到驱动,最终到Linux,研究过java虚拟机,虽然没研究过ART或者老牌的Dalvik虚拟机,但原理都差不多,并不影响我对android有一个全局的认识,今天我们的主题是架构,其实对架构的理解一定要宏观一点,大到手机操作系统架构,小到代码逻辑设计的架构,一句老话讲的好,也代表了我对架构的整体理解:没有最好的架构,只有最合适的架构。下面我们聊聊,一个好的架构是什么样子的,该怎么去判断呢。
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (mInputEventConsistencyVerifier != null) {
mInputEventConsistencyVerifier.onKeyEvent(event, 1);
}
//ViewGroup是focused或者设置了具体的大小,则交给它实现
if ((mPrivateFlags & (PFLAG_FOCUSED | PFLAG_HAS_BOUNDS))
== (PFLAG_FOCUSED | PFLAG_HAS_BOUNDS)) {
//在View中的实现
if (super.dispatchKeyEvent(event)) {
return true;
}
} else if (mFocused != null && (mFocused.mPrivateFlags & PFLAG_HAS_BOUNDS)
== PFLAG_HAS_BOUNDS) {
//mFocused表示当前ViewGroup中获得焦点或者包含焦点的View(子View)
if (mFocused.dispatchKeyEvent(event)) {
return true;
}
}
if (mInputEventConsistencyVerifier != null) {
mInputEventConsistencyVerifier.onUnhandledEvent(event, 1);
}
return false;
}
复制代码
从上面代码可以看出,子View想要获得焦点,处理KeyEvent,需要设置focusable属性为true。KeyEvent会优先派发给符合条件的ViewGroup处理,而不是子View。mFocused.dispatchKeyEvent(event)
中的dispatchKeyEvent()
可能会迭代调用,因为子View也可能是ViewGroup。
这里看看View中事件分发。
//View
/**
- 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
ListenerInfo li = mListenerInfo;
//如果我们给View设置了OnKeyListener且View是ENABLED状态,
//则会回调我们的了OnKeyListener
if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
&& li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
return true;
}
//调用KeyEvent.dispatch方法,并将view对象本身作为参数传递进去,view的各种callback方法在这里被触发
if (event.dispatch(this, mAttachInfo != null
? mAttachInfo.mKeyDispatchState : null, this)) {
return true;
}
if (mInputEventConsistencyVerifier != null) {
mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
}
return false;
}
复制代码
ViewGroup和View的dispatchKeyEvent()
就构成了View层次结构的KeyEvent分发,且总是从树根DecorView开始到具体的View。注意到此处在View不消费KeyEvent会调用KeyEvent.dispatch方法,在Activity也会调用该方法。
//KeyEvent
public final boolean dispatch(Callback receiver, DispatcherState state,
Object target) {
switch (mAction) {
case ACTION_DOWN: {
mFlags &= ~FLAG_START_TRACKING;
//回调Callback对象receiver的onKeyDown函数,上文知道Activity和View都实现Callback
boolean res = receiver.onKeyDown(mKeyCode, this);
if (state != null) {//通常成立
if (res && mRepeatCount == 0 && (mFlags&FLAG_START_TRACKING) != 0) {//判断是否轨迹事件
state.startTracking(this, target);
} else if (isLongPress() && state.isTracking(this)) {
try {
//处理长按事件
if (receiver.onKeyLongPress(mKeyCode, this)) {
state.performedLongPress(this);
res = true;//消费该事件
}
} catch (AbstractMethodError e) {
}
}
}
return res;
}
case ACTION_UP:
if (state != null) {
//reset state的内部状态,也改变了KeyEvent的某些状态
state.handleUpEvent(this);
}
//回调Callback对象receiver的onKeyUp函数
return receiver.onKeyUp(mKeyCode, this);
case ACTION_MULTIPLE:
final int count = mRepeatCount;
final int code = mKeyCode;
if (receiver.onKeyMultiple(code, count, this)) {
return true;
}
if (code != KeyEve