Android按键事件处理流程 -- KeyEvent
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Android按键事件处理流程 -- KeyEvent
2014/6/24 13:18:58 xiaoweiz 程序员俱乐部我要评论(0)
•
•
•
刚接触Android开发的时候,对touch、key事件的处理总是一知半解,一会是Activity里的方法,一会是各种View
中的,自己始终不清楚到底哪个在先哪个在后,总之对整个处理流程没能很好的把握。
每次写这部分代码的时候都有些心虚,
因为我不是很清楚什么时候、以什么样的顺序被调用,大都是打下log看看,没问题就算ok了。但随着时间流逝,这种感觉一直
折磨着我。期间也在网上搜索了相关资料,但总感觉不是那么令人满意。自打开始研究Android源码起,这部分内容的分析早就
被列在我的TODO list上了。因为弄懂这部分处理逻辑对明明白白地写android程序实在是太重要了,所以今天我就带领大家看看
这部分的处理逻辑。touch事件的处理我将放在另一篇博客中介绍(相比KeyEvent,大体都一样,只是稍微复杂些)。
为了突出本文的重点,我们直接从事件被派发到View层次结构的根节点DecorView 开始分析,这里我们先来看看DecorView#
dispatchKeyEvent方法,代码如下:
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
final int keyCode = event.getKeyCode();
final int action = event.getAction();
final boolean isDown = action == KeyEvent.ACTION_DOWN;
/// 1. 第一次down事件的时候,处理panel的快捷键
if (isDown && (event.getRepeatCount() == 0)) {
// First handle chording of panel key: if a panel key is held // but not released, try to execute a shortcut in it.
if ((mPanelChordingKey > 0) && (mPanelChordingKey != keyCode)) {
boolean handled = dispatchKeyShortcutEvent(event);
if (handled) {
return true;
}
}
// If a panel is open, perform a shortcut on it without the // chorded panel key
if ((mPreparedPanel != null) && mPreparedPanel.isOpen) { if (performPanelShortcut(mPreparedPanel, keyCode, event, 0)) {
return true;
}
}
}
/// 2. 这里是我们本文的重点,当window没destroy且其Callback 非空的话,交给其Callback处理
if (!isDestroyed()) { // Activity、Dialog都是Callback接口的实现
final Callback cb = getCallback(); // mFeatureId < 0 表示是application的DecorView,比如Activity、Dialog
final boolean handled = cb != null && mFeatureId < 0 ? cb.dispatchKeyEvent(event) // 派发给callback的方法
: super.dispatchKeyEvent(event); // 否则直接派发到ViewGroup#dispatchKeyEvent(View层次结构)
if (handled) {
return true; // 如果被上面的步骤处理了则直接返回true,不再往下传递
}
}
/// 3. 这是key事件的最后一步,如果到这一步还没处理掉,则派发到PhoneWindow对应的onKeyDown, onKeyUp方法
return isDown ? PhoneWindow.this.onKeyDown(mFeatureId, event.getKeyCode(), event)
: PhoneWindow.this.onKeyUp(mFeatureId,
event.getKeyCode(), event);
}
接下来我们按照这个派发顺序依次来看看相关方法的实现,这里先看看
Activity(Callback)的dispatchKeyEvent实现:
/**
* 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.
*/
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
/// 2.1. 回调接口,实际开发中用处不大,你感兴趣可以参看其方法doc onUserInteraction();
Window win = getWindow();
/// 2.2. 从这里事件的处理交给了与之相关的window对象,实质是派发到了view层次结构
if (win.superDispatchKeyEvent(event)) {
return true;
}
View decor = mDecor;
if (decor == null) decor = win.getDecorView();
/// 2.3. 到这里如果view层次结构没处理则交给KeyEvent本身的dispatch方法,Activity的各种回调方法会被触发