您的位置:首页 > 移动开发 > Android开发

Android应用程序键盘(Keyboard)消息处理机制分析(20)

2011-10-24 00:59 579 查看
Step 24. InputQueue.dispatchKeyEvent

这个函数定义在frameworks/base/core/java/android/view/InputQueue.java文件中:

public final class InputQueue {

......

private static void dispatchKeyEvent(InputHandler inputHandler,

KeyEvent event, long finishedToken) {

Runnable finishedCallback = FinishedCallback.obtain(finishedToken);

inputHandler.handleKey(event, finishedCallback);

}

......

}

这个函数首先会创建一个FinishedCallback类型的对象finishedCallback,FinishedCallback是InputQueue的一个内部类,它继承于Runnable类。这个finishedCallback对象是提供给当前Activity窗口的,当它处理完毕键盘事件后,需要通过消息分发的方式来回调这个finishedCallback对象,以及InputQueue类处理一个手尾的工作,后面我们会分析到。

这里的inputHandler对象是在前面分析应用程序注册键盘消息接收通道的过程时,在Step 1(ViewRoot.setView)中传进来的:

InputQueue.registerInputChannel(mInputChannel, mInputHandler,

Looper.myQueue());

它是ViewRoot类的一个成员变量mInputHandler。因此,这里将调用ViewRoot类的内部对象mInputHandler的成员函数handleKey来处理键盘事件。

Step 25. InputHandler.handleKey
这个函数定义在frameworks/base/core/java/android/view/ViewRoot.java文件中:

public final class ViewRoot extends Handler implements ViewParent,

View.AttachInfo.Callbacks {

......

private final InputHandler mInputHandler = new InputHandler() {

public void handleKey(KeyEvent event, Runnable finishedCallback) {

startInputEvent(finishedCallback);

dispatchKey(event, true);

}

......

};

......

}

这个函数首先调用其外部类ViewRoot的startInputEvent成员函数来把回调对象finishedCallback保存下来:

public final class ViewRoot extends Handler implements ViewParent,

View.AttachInfo.Callbacks {

......

private void startInputEvent(Runnable finishedCallback) {

......

mFinishedCallback = finishedCallback;

}

......

}

然后再调用其外部类ViewRoot的dispatchKey成员函数来进一步处这个键盘事件。

Step 26. ViewRoot.dispatchKey
这个函数定义在frameworks/base/core/java/android/view/ViewRoot.java文件中:

public final class ViewRoot extends Handler implements ViewParent,

View.AttachInfo.Callbacks {

......

private void dispatchKey(KeyEvent event, boolean sendDone) {

......

Message msg = obtainMessage(DISPATCH_KEY);

msg.obj = event;

msg.arg1 = sendDone ? 1 : 0;

......

sendMessageAtTime(msg, event.getEventTime());

}

......

}

ViewRoot不是直接处理这个键盘事件,而是把作为一个消息(DISPATCH_KEY)它放到消息队列中去处理,这个消息最后由ViewRoot类的deliverKeyEvent成员函数来处理。

Step 27. ViewRoot.deliverKeyEvent

这个函数定义在frameworks/base/core/java/android/view/ViewRoot.java文件中:

public final class ViewRoot extends Handler implements ViewParent,

View.AttachInfo.Callbacks {

......

private void deliverKeyEvent(KeyEvent event, boolean sendDone) {

// If mView is null, we just consume the key event because it doesn't

// make sense to do anything else with it.

boolean handled = mView != null

? mView.dispatchKeyEventPreIme(event) : true;

......

// If it is possible for this window to interact with the input

// method window, then we want to first dispatch our key events

// to the input method.

if (mLastWasImTarget) {

InputMethodManager imm = InputMethodManager.peekInstance();

if (imm != null && mView != null) {

......

imm.dispatchKeyEvent(mView.getContext(), seq, event,

mInputMethodCallback);

return;

}

}

......

}

......

}

ViewRoot在把这个键盘事件分发给当前激活的Activity窗口处理之前,首先会调用InputMethodManager的dispatchKeyEvent成员函数来处理这个键盘事件。InputMethodManager处理完这个键盘事件后,再回调用这里的mInputMethodCallback对象的finishedEvent成员函数来把键盘事件分发给当前激活的Activity窗口处理。当然,在把这个键盘事件分发给InputMethodManager处理之前,ViewRoot也会先把这个键盘事件分发给当前激活的Activity窗口的dispatchKeyEventPreIme成员函数处理。

Step 28. InputMethodManager.dispatchKeyEvent
这个函数定义在frameworks/base/core/java/android/view/inputmethod/InputMethodManager.java文件中。这是一个输入法相关的类,我们这里就不关注了,只要知道当输入法处理完成之后,它就会调用ViewRoot类的mInputMehtodCallback对象的finishedEvent成员函数。
Step 29. InputMethodCallack.finishedEvent
这个函数定义在frameworks/base/core/java/android/view/ViewRoot.java文件中:

public final class ViewRoot extends Handler implements ViewParent,

View.AttachInfo.Callbacks {

......

static class InputMethodCallback extends IInputMethodCallback.Stub {

private WeakReference<ViewRoot> mViewRoot;

public InputMethodCallback(ViewRoot viewRoot) {

mViewRoot = new WeakReference<ViewRoot>(viewRoot);

}

public void finishedEvent(int seq, boolean handled) {

final ViewRoot viewRoot = mViewRoot.get();

if (viewRoot != null) {

viewRoot.dispatchFinishedEvent(seq, handled);

}

}

......

}

......

}

这个函数最终调用ViewRoot的dispatchFinishedEvent来进一步处理。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息