Input事件输入系统之应用MotionEvent触摸事件处理流程
输入事件一般分为KeyEvent按键事件,和MotionEvent触摸事件,也就是我们平时说的touch事件,事件的传递流程相当复杂庞大,
我们先暂时绕开那个庞大的系统来谈谈上层应用如何接收到MotionEvent事件然后处理的,在讲这个之
前我们先提几个相关类:
Window,WindowManager,PhoneWindow,IWindowManager,WindowManagerService,咋一看,这些东西都是与Window有关
的,平时我们用的也蛮多的也就是WindowManager对象,这些东西是怎么如何我们的MotionEvent事件相关联起来的,这就是我们接
下来分析的重点。由于我们就是简单的分析下应用层的输入输出事件的分析,所以Input系统的硬件抽象层我们只是简答的提一
下。等下次的时候在重点分析该流程的通信协议。
由于有的客官已经知道了Activity的启动流程,那么我们就抽出与我们事件传递相关的一点点东西,view的加载流程,结合我们之前
提到的几个window的概念来分析与MotionEvent事件的联系
首先我们来看下Activity的attach函数
final void attach(Context context, ActivityThread aThread,
Instrumentation instr, IBinder token, int ident,
Application application, Intent intent, ActivityInfo info,
CharSequence title, Activity parent, String id,
NonConfigurationInstances lastNonConfigurationInstances,
Configuration config, String referrer, IVoiceInteractor voiceInteractor,
Window window) {
attachBaseContext(context);
mFragments.attachHost( null /*parent*/ );
mWindow = new PhoneWindow( this, window);
w mWindow.setWindowControllerCallback( this);
//很重要的一个接口回调设置,因为事件传入Activity需要这个接口回调的传递,这点后面我们会继续分析。
w mWindow.setCallback( this);
w mWindow.setOnWindowDismissedCallback( this);
w mWindow.getLayoutInflater().setPrivateFactory( this);
。。。。。。。。。。中间省略
w mWindow.setWindowManager(
(WindowManager)context.getSystemService(Context. WINDOW_SERVICE ),
mToken, mComponent.flattenToString(),
(info. flags & ActivityInfo. FLAG_HARDWARE_ACCELERATED ) != 0);
if ( mParent != l null) {
w mWindow.setContainer( mParent.getWindow());
}
mWindowManager = mWindow.getWindowManager();
从上面的函数中,我们可以看到我们上面提过的几个window概念了,
我们先看下我们的mWindow到底是什么东西
private Window mWindow;
由上面的方法里面可知,原来我们是new了一个PhoneWindow对象,而我们的PhoneWindow就是Window抽象类的继承类
那么我们接下来分析activity中的 onCreate 方法 中的setContentView方法
从字面意思上我们可以理解为填充内容的view,那么他是怎么填充进去的,我们继续分析
public void setContentView(@LayoutRes int layoutResID) {
getWindow().setContentView(layoutResID);
initWindowDecorActionBar();
}
原来他是通过PhoneWindow来调用setContetnView方法的,那么我们继续分析该方法
相信很多同学都知道该方法,其实就是实例化一个 DecoreView ,然后把我们的 contentView 填充到 DecoreView 中
那么我们是这么把这个 decoreviewt 填充到我们的 Window 中的呢,其实接下来我们就要说说我们的 WindowManager 的作用。
那么我们就继续看 view 填充过程,在我们的 Activity 调用 OnResume 之前我们需要调用主线程 ActivityThread 的 handleOnresume 来
把我们的 View 填充到 window 中,废话不多说我们来分析下:
ActivityThread.java
final void handleResumeActivity(IBinder token,
boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
if (r. window == null && !a.mFinished && willBeVisible) {
final Activity a = r.activity;
r. window = r. activity.getWindow();
View decor = r.w window.getDecorView();
decor.setVisibility(View. INVISIBLE );
ViewManager wm = a.getWindowManager();
WindowManager.LayoutParams l = r. window.getAttributes();
a.mDecor = decor;
l. type = WindowManager.LayoutParams. TYPE_BASE_APPLICATION ;
l. softInputMode |= forwardBit;
if (r. mPreserveWindow) {
a.mWindowAdded = true;
r. mPreserveWindow = false;
// Normally the ViewRoot