EditText中输入键1,系统发生了什么?

按键会触发触发消息,发送到MessageQueue中,消息内容为:
{ when=-20s330ms what=11 obj=KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_1, scanCode=0, metaState=0, flags=0x6, repeatCount=0, eventTime=3939450, downTime=3939450, deviceId=-1, source=0x0 } target=android.view.ViewRootImpl$ViewRootHandler }
这条消息在ViewRootImpl$ViewRootHandler中处理,对应的hanleMessage部分为
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_DISPATCH_KEY_FROM_IME: {
if (LOCAL_LOGV) Log.v(
TAG, "Dispatching key "
+ msg.obj + " from IME to " + mView);
KeyEvent event = (KeyEvent)msg.obj;
if ((event.getFlags()&KeyEvent.FLAG_FROM_SYSTEM) != 0) {
// The IME is trying to say this event is from the
// system! Bad bad bad!
//noinspection UnusedAssignment
event = KeyEvent.changeFlags(event, event.getFlags() &
~KeyEvent.FLAG_FROM_SYSTEM);
}
enqueueInputEvent(event, null, QueuedInputEvent.FLAG_DELIVER_POST_IME, true);
} break;

在ViewRootImpl中跳转几次后进入processKeyEvent方法
private int processKeyEvent(QueuedInputEvent q) {
final KeyEvent event = (KeyEvent)q.mEvent;

// Deliver the key to the view hierarchy.
// 调用了View的dispatchKeyEvent方法,其中mView是PhoneWindow$DecorView
if (mView.dispatchKeyEvent(event)) {
return FINISH_HANDLED;
}
//.....
return FORWARD;
}

从DecorView开始执行若干次dispatchKeyEvent(event),将KeyEvent最终分发到TextView中执行TextView的onKeyDown()方法:
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
int which = doKeyDown(keyCode, event, null);
if (which == 0) {
return super.onKeyDown(keyCode, event);
}

return true;
}
在onKeyDown()方法的一开始执行了TextView的doKeyDown()
public boolean onKeyDown(int keyCode, KeyEvent event) {
int which = doKeyDown(keyCode, event, null);
if (which == 0) {
return super.onKeyDown(keyCode, event);
}

return true;
}
这个函数第一行执行TextView的doKeyDown()方法,跟踪进去
private int doKeyDown(int keyCode, KeyEvent event, KeyEvent otherEvent)『
if (mEditor != null && mEditor.mKeyListener != null) {
if (doDown) {
beginBatchEdit();
final boolean handled = mEditor.mKeyListener.onKeyDown(this, (Editable) mText,
keyCode, event);
endBatchEdit();
hideErrorIfUnchanged();
if (handled) return 1;
}
}
}
这个方法执行那个了mKeyListerner.onKeyDown()方法:
@Override
public boolean onKeyDown(View view, Editable content,
int keyCode, KeyEvent event) {
KeyListener im = getKeyListener(event);

return im.onKeyDown(view, content, keyCode, event);
}
通过getKeyListener(event)来判断KeyEvent对应的KeyListener,然后执行对应的onKeyDown。
对于按键1,对于的KeyListener为QwertyKeyListener,QwertyKeyListener.onKeyDown()为:
public boolean onKeyDown(View view, Editable content,
int keyCode, KeyEvent event) {
//...
content.replace(selStart, selEnd, String.valueOf((char) i));
//...
}
这其中调用了SpannableStringBuilder的replace方法:
public SpannableStringBuilder replace(final int start, final int end,
CharSequence tb, int tbstart, int tbend) {
//...
TextWatcher[] textWatchers = getSpans(start, start + origLen, TextWatcher.class);
sendBeforeTextChanged(textWatchers, start, origLen, newLen);

change(start, end, tb, tbstart, tbend);

//...
sendTextChanged(textWatchers, start, origLen, newLen);
sendAfterTextChanged(textWatchers);

// Span watchers need to be called after text watchers, which may update the layout
sendToSpanWatchers(start, end, newLen - origLen);

return this;
}

这个方法获得了TextView所有的TextWatcher,然后发送BeforeTextChanged消息,之后调用change()方法真正
改变了TextView中的内容。然后发送OnTextChanged和AfterTextChanged方法。

这样一个流程可以简单概括成这样几步:
1.按下键盘后系统发送一个KeyDown的消息到MainLooper的MessageQueue.
2.ViewRootImpl$ViewRootHandler处理KeyDown消息,调用DecorView的dispatchKeyEvent进行分发
3.DocoreView将KeyEvent分发到TextView执行TextView的doKeyDown()方法。
4.TextView调用mKeyListener.onKeyDown()方法。
5.最终调用合适的KeyListener(这儿为QwertyKeyListener)的onKeyDown()方法,改变TextView中的mText值

时间: 2024-12-07 06:41:06

EditText中输入键1,系统发生了什么?的相关文章

【XFeng安卓开发笔记】edittext中怎样禁止系统自带键盘弹出但光标还在

网上又不少方法,均告失败,最终找到以下的方法: // 隐藏系统键盘 public void hideSoftInputMethod(EditText ed) { getWindow().setSoftInputMode( WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN); int currentVersion = android.os.Build.VERSION.SDK_INT; String methodName = null

在EditText中限制输入,自定义样式,监听输入的字符,自动换行

自动获取焦点 <!-- 添加:<requestFocus /> 会自动获取焦点 --> <EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:ems="10" android:gravity="center_horizontal" android:hint="自

Android EditText中字符大小与光标位置

最近的工作需要自己写一个数字键盘用于数字的输入,采用的方法是自定义一个  Dialog,然后将数字显示在EditText中.在处理过程中遇到遇到一个问题,在EditText的点击事件中屏蔽系统键盘并弹出自定义的Dialog,无法获取用户选中的字符即Selection,造成的问题现象是用户不能选中中间某个位置修改输入值. 为了解决这一问题,需要在EditText的点击事件中获取Selection. 解决方法是:1.在EditText点击事件中获取用户点击位置,主要取其中的touchX值(这里主要讨

EditText中输入信息的限制的方法

应用场景 在Android应用中有时需要EditText中只允许输入约定的一些字符,禁止输入其他字符.这里列举了一些可能的应用场景. 1. 场景一 在通讯录保存好友信息界面中填写好友的电话号码时,应当只能输入数字,禁止输入其他字符. 2. 场景二 在登录界面中输入用户名和密码时,由于很多账号系统都不支持中文的用户名和密码,只允许使用英文字母和数字.如果可以禁止在输入框中输入中文可以减少不必要的登录验证过程,也方便了用户操作. 3. 场景三 在邮箱地址的输入框中,应当只允许输入英文字母,数字和@.

Linux内核中的GPIO系统之(3):pin controller driver代码分析--devm_kzalloc使用【转】

转自:http://www.wowotech.net/linux_kenrel/pin-controller-driver.html 一.前言 对于一个嵌入式软件工程师,我们的软件模块经常和硬件打交道,pin control subsystem也不例外,被它驱动的硬件叫做pin controller(一般ARM soc的datasheet会把pin controller的内容放入GPIO controller的章节中),主要功能包括: (1)pin multiplexing.基于ARM core

现代IM系统中的消息系统架构

前言IM全称是『Instant Messaging』,中文名是即时通讯.在这个高度信息化的移动互联网时代,生活中IM类产品已经成为必备品,比较有名的如钉钉.微信.QQ等以IM为核心功能的产品.当然目前微信已经成长为一个生态型产品,但其核心功能还是IM.还有一些非以IM系统为核心的应用,最典型的如一些在线游戏.社交应用,IM也是其重要的功能模块.可以说,IM系统已经是任何一个带有社交属性的应用需要具备的基础功能,网络上对于这类系统的设计与实现的讨论也越来越多. IM系统在互联网初期即存在,其基础技

c#语言-多线程中的锁系统

介绍 平常在多线程开发中,总避免不了线程同步.这次就对net多线程中的锁系统做个简单描述. 目录 一:lock.Monitor 1:基础. 2: 作用域. 3:字符串锁. 二: mutex 三:Semaphore 四:总结 一:lock.Monitor 1:基础 Lock是Monitor语法糖简化写法.Lock在IL会生成Monitor. //======Example 1===== string obj = "helloworld"; lock (obj) { Console.Wri

double类型的数值在EditText中显示?

============问题描述============ double类型的数值在EditText中显示?et_count.setText(double型数值) 报错,请问应该怎么写? ============解决方案1============ 你要用String.valueof(double value) ============解决方案2============ et_count.setText(String.valueOf(double型数值)) ============解决方案3====

Eclipse中添加Android系统jar包

这样做的好处是,可以使用Eclipse开发系统应用了,这样可以调用系统中才使用的API. 1.首先在项目中右击->属性.如图所示依次操作 2.添加User Library 3.第一次要新建User Library名字 注:一定要勾选上System library(addedto the boot class path)否则会出现错误1. 4.添加jar包 2.${ANDROID_SOURCE}/out/target/common/obj/JAVA_LIBRARIES/framework_inte