写在之前,说到Android的事件分发和View绘制,我们常接触到的是从Activity的dispatchTouchEvent()和顶级DecorView的draw方法开始,但是一个对象的方法调用总是有源头的,而对象也肯定是有初始化的过程的,日常中我们不用关心这个Activity是如何由class文件变成一个内存中的对象,也不需要知道我们的顶级视图DecorView又是什么时候初始化出来的,当然也不需要关心DecorView是如何和我们常说的Window关联起来的,以及进一步我们的一个个页面又是如何被系统管理的。但一个东西用的多了,就会总是想要知道它是从哪里来的,一件事请发生了也总想知道引起这件事的最初源头是在哪里,这在现实的生活中也许是根本不可能,但万幸在代码中却给了我们机会去追本溯源(这正是代码的乐趣之一,所有的规则和逻辑都是有同样的人去code的,而不至于出现像在现实中:人类存在的意义?这些无法回答的问题),当然也许这依旧并没有什么意义。但是这里我还是简单理出Activity中的dispatchTouchEvent()是由谁调用的,DecorView的draw方法又是由谁调用,以及该调用者又是在什么时候以及如何初始化的。也就是去找一找事件分发在应用层的起点是在哪里以及一个View树最开始的绘制起点又是在哪里。
本文中我们就从Activity的初始化开始,跟着Activiy的初始化过程去找一找事件分发和View树绘制的起点是在哪里。本文内容为个人理解和笔记整理,肯定有错误及不准确的地方万请仅作参考查看,如有错误还请指出
<下面涉及到的Android源码均为API23的源码>
在Activity的整个初始化过程中涉及到的对象有很多,其中比较重要的有:ActivityThread,AvtivityManagerServier,Activity,WindowManager,WindowManagerImpl,WindowManagerGlobal,ViewRootImpl,Context,Window,PhoneWindow,DecorView,我们可以先有个印象:
关于Activity的启动,主要分为当前应用的其他Activity启动和跨应用的的Activity启动(比如点击Launcher图标启动一个app的MainActivity),此处我们不去过于关注在调用startActivity()之后AMS是怎么管理这个Activity的,我们直接跳到要启动的Activity在AMS中注册登记之后,又回到ActivityThread主线程中执行handleLaunchActivity()的地方开始,而对于这之前的过程我们以手机来举一个不太恰当的例子带过:
代码如下:
@ActivityThread.java
//-------1.1.1ActivityThread在收到LaunchActivity的消息后(此时该Activity已经在AMS的栈中存在记录了,只不过这个记录不是这个Activity的实体或者引用,因为此时该Activity还没有创建,只是一个对应的特征信息,而AMS可以通过这个特征信息找到该Activity。)(TODO 完善目前看到的是一个binder)
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
// If we are getting ready to gc after going to the background, well
// we are back active so skip it.
unscheduleGcIdler();
mSomeActivitiesChanged = true;
if (r.profilerInfo != null) {
mProfiler.setProfiler(r.profilerInfo);
mProfiler.startProfiling();
}
// Make sure we are running with the most recent config.
handleConfigurationChanged(null, null);
if (localLOGV) Slog.v(
TAG, "Handling launch of " + r);
// Initialize before creating the activity
WindowManagerGlobal.initialize();
Activity a = performLaunchActivity(r, customIntent);//--------------1.1.2、执行 performLaunchActivity,
if (a != null) {//--------------如果a!=null,继续往下走
r.createdConfig = new Configuration(mConfiguration);
Bundle oldState = r.state;
handleResumeActivity(r.token, false, r.isForward,
!r.activity.mFinished && !r.startsNotResumed);//-------------1.1.3、在performLaunchActivity()调用完毕之后,如果成功启动了对应所需的Activity,则此时会继续调用handleResumeActivity()
if (!r.activity.mFinished && r.startsNotResumed) {//---------------已经start但是没有onResum
// The activity manager actually wants this one to start out
// paused, because it needs to be visible but isn't in the
// foreground. We accomplish this by going through the
// normal startup (because activities expect to go through
// onResume() the first time they run, before their window
// is displayed), and then pausing it. However, in this case
// we do -not- need to do the full pause cycle (of freezing
// and such) because the activity manager assumes it can just
// retain the current state it has.
try {
r.activity.mCalled = false;
mInstrumentation.callActivityOnPause(r.activity);
// We need to keep around the original state, in case
// we need to be created again. But we only do this
// for pre-Honeycomb apps, which always save their state
// when pausing, so we can not have them save their state
// when restarting from a paused state. For HC and later,
// we want to (and can) let the state be saved as the normal
// part of stopping the activity.
if (r.isPreHoneycomb()) {
r.state = oldState;
}
if (!r.activity.mCalled) {
throw new SuperNotCalledException(
"Activity " + r.intent.getComponent().toShortString() +
" did not call through to super.onPause()");
}
} catch (SuperNotCalledException e) {
throw e;
} catch (Exception e) {
if (!mInstrumentation.onException(r.activity, e)) {
throw new RuntimeException(
"Unable to pause activity "
+ r.intent.getComponent().toShortString()
+ ": " + e.toString(), e);
}
}
r.paused = true;
}
} else {
// If there was an error, for any reason, tell the activity
// manager to stop us.
try {
ActivityManagerNative.getDefault()
.finishActivity(r.token, Activity.RESULT_CANCELED, null, false);
} catch (RemoteException ex) {
// Ignore
}
}
}
代码:
@ActivityThread.java
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
// System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");
ActivityInfo aInfo = r.activityInfo;
if (r.packageInfo == null) {
r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
Context.CONTEXT_INCLUDE_CODE);
}
ComponentName component = r.intent.getComponent();
if (component == null) {
component = r.intent.resolveActivity(
mInitialApplication.getPackageManager());
r.intent.setComponent(component);
}
if (r.activityInfo.targetActivity != null) {
component = new ComponentName(r.activityInfo.packageName,
r.activityInfo.targetActivity);
}
Activity activity = null;
try {
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();//-----------------1.2.1拿取ClassLoader 加载activity的字节码,生成activity对象,在此之前已经把该activity对应的信息以clasinfo或intent中的action等信息为标记在AMS的activity栈中添加。以后AMS则可以通过此找到该Activity并发送消息执行其相应的生命周期回调
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
r.intent.prepareToEnterProcess();
if (r.state != null) {
r.state.setClassLoader(cl);
}
} catch (Exception e) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to instantiate activity " + component
+ ": " + e.toString(), e);
}
}
try {
Application app = r.packageInfo.makeApplication(false, mInstrumentation);//---------------1.2.2准备Application
if (localLOGV) Slog.v(TAG, "Performing launch of " + r);
if (localLOGV) Slog.v(
TAG, r + ": app=" + app
+ ", appName=" + app.getPackageName()
+ ", pkg=" + r.packageInfo.getPackageName()
+ ", comp=" + r.intent.getComponent().toShortString()
+ ", dir=" + r.packageInfo.getAppDir());
if (activity != null) {
Context appContext = createBaseContextForActivity(r, activity);//-----------1.2.3生成Context
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
Configuration config = new Configuration(mCompatConfiguration);
if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
+ r.activityInfo.name + " with config " + config);
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config,
r.referrer, r.voiceInteractor);//-----------1.2.4执行Activity的attacth方法
if (customIntent != null) {
activity.mIntent = customIntent;
}
r.lastNonConfigurationInstances = null;
activity.mStartedActivity = false;
int theme = r.activityInfo.getThemeResource();
if (theme != 0) {
activity.setTheme(theme);//----**tip:设置teme,需要在setContentView之前,否则setContentView在onCreat中调用时拿不到Theme的值**-----
}
activity.mCalled = false;
if (r.isPersistable()) {//----------------1.2.5、不管如何都会回调到activity的onCreat方法,此处的mInstrumentation对象也是一个比较有意思的地方,在Activity中的onCreate()中,会有常见的setContentView方法,在该方法中最终会在PhoneWindow中生成DecorView并和PhoneWindow相关联
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
if (!activity.mCalled) {
throw new SuperNotCalledException(
"Activity " + r.intent.getComponent().toShortString() +
" did not call through to super.onCreate()");
}
r.activity = activity;//----在r中记录对应的activity
r.stopped = true;
if (!r.activity.mFinished) {
activity.performStart();//----------------1.2.6回调Activity的onStart()
r.stopped = false;
}
if (!r.activity.mFinished) {//-----------------1.2.7.回调OnRestoreInstanceState
if (r.isPersistable()) {
if (r.state != null || r.persistentState != null) {
mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,
r.persistentState);
}
} else if (r.state != null) {
mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
}
}
if (!r.activity.mFinished) {
activity.mCalled = false;
if (r.isPersistable()) {
mInstrumentation.callActivityOnPostCreate(activity, r.state,
r.persistentState);
} else {
mInstrumentation.callActivityOnPostCreate(activity, r.state);
}
if (!activity.mCalled) {
throw new SuperNotCalledException(
"Activity " + r.intent.getComponent().toShortString() +
" did not call through to super.onPostCreate()");
}
}
}
r.paused = true;
mActivities.put(r.token, r);//----最终保存该Activity
} catch (SuperNotCalledException e) {
throw e;
} catch (Exception e) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to start activity " + component
+ ": " + e.toString(), e);
}
}
return activity;
}
代码如下:
@Activity
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) {
attachBaseContext(context);
mFragments.attachHost(null /*parent*/);
mWindow = new PhoneWindow(this);//-----1.3.1.创建phoneWindow对象,并保存到本地
mWindow.setCallback(this);//-----1.3.2.把PhoneWindow对象的callBack设置为this,该CallBack是Window.Callback,主要用于在接收到TouchEvent和KeyEvent的事件时回调对应Activity中的dispatchTouchEvent()和KeyEvent的方法
mWindow.setOnWindowDismissedCallback(this);
mWindow.getLayoutInflater().setPrivateFactory(this);
if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
mWindow.setSoftInputMode(info.softInputMode);
}
if (info.uiOptions != 0) {
mWindow.setUiOptions(info.uiOptions);
}
mUiThread = Thread.currentThread();
mMainThread = aThread;
mInstrumentation = instr;
mToken = token;
mIdent = ident;
mApplication = application;
mIntent = intent;
mReferrer = referrer;
mComponent = intent.getComponent();
mActivityInfo = info;
mTitle = title;
mParent = parent;
mEmbeddedID = id;
mLastNonConfigurationInstances = lastNonConfigurationInstances;
if (voiceInteractor != null) {
if (lastNonConfigurationInstances != null) {
mVoiceInteractor = lastNonConfigurationInstances.voiceInteractor;
} else {
mVoiceInteractor = new VoiceInteractor(voiceInteractor, this, this,
Looper.myLooper());
}
}
mWindow.setWindowManager(
(WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
mToken, mComponent.flattenToString(),
(info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);//-----1.3.3、给phoneWindow设置WindowManager
if (mParent != null) {
mWindow.setContainer(mParent.getWindow());
}
mWindowManager = mWindow.getWindowManager();//同时保存WindowManager到Activity中
mCurrentConfig = config;
}
我们回顾一下顶级视图DecorView是怎么和Activity关联起来的:首先是在接收到LaunchActivity指令之后,实例化Activity进而执行Activity的attatch()此时创建PhoneWindow对象并使其和WindowManager关联(TODO:具体如何管理),同时Activity中会保存该PhoneWindow,然后又在Activity的onCreate()中setContentView()时,创建DecorView,这样Activity就和DecorView关联起来了。
@ActivityThread.java
final void handleResumeActivity(IBinder token,
boolean clearHide, boolean isForward, boolean reallyResume) {
// If we are getting ready to gc after going to the background, well
// we are back active so skip it.
unscheduleGcIdler();
mSomeActivitiesChanged = true;
// TODO Push resumeArgs into the activity for consideration
ActivityClientRecord r = performResumeActivity(token, clearHide);//------1.4.1回调Activity的onReusme()
if (r != null) {
final Activity a = r.activity;
if (localLOGV) Slog.v(
TAG, "Resume " + r + " started activity: " +
a.mStartedActivity + ", hideForNow: " + r.hideForNow
+ ", finished: " + a.mFinished);
final int forwardBit = isForward ?
WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION : 0;
// If the window hasn't yet been added to the window manager,
// and this guy didn't finish itself or start another activity,
// then go ahead and add the window.
boolean willBeVisible = !a.mStartedActivity;
if (!willBeVisible) {
try {
willBeVisible = ActivityManagerNative.getDefault().willActivityBeVisible(
a.getActivityToken());
} catch (RemoteException e) {
}
}
if (r.window == null && !a.mFinished && willBeVisible) {
r.window = r.activity.getWindow();//--------1.4.2、该处拿取之前在attach时,创建的PhoneWindow
View decor = r.window.getDecorView();//--------1.4.3、此处会拿取DecorView,DecorView是PhoneWindow的内部类,当没有时会直接创建,第一次创建是在Oncreat的setContentView中创建的
decor.setVisibility(View.INVISIBLE);
ViewManager wm = a.getWindowManager();//-------1.4.4、拿取WindowManager,实际返回的是其实现类WindowManagerImpl
WindowManager.LayoutParams l = r.window.getAttributes();
a.mDecor = decor;
l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
l.softInputMode |= forwardBit;
if (a.mVisibleFromClient) {
a.mWindowAdded = true;
wm.addView(decor, l);//--------1.4.5、此处执行WindowManager的AddView(),该调用处会生成ViewRootImpl,并把DecorView和ViewRootImpl保存起来,一一对应,而Activity中的事件分发和Activity的视图绘制都是从ViewRootImpl中直接开始的
}
// If the window has already been added, but during resume
// we started another activity, then don't yet make the
// window visible.
} else if (!willBeVisible) {
if (localLOGV) Slog.v(
TAG, "Launch " + r + " mStartedActivity set");
r.hideForNow = true;
}
// Get rid of anything left hanging around.
cleanUpPendingRemoveWindows(r);
// The window is now visible if it has been added, we are not
// simply finishing, and we are not starting another activity.
if (!r.activity.mFinished && willBeVisible
&& r.activity.mDecor != null && !r.hideForNow) {
if (r.newConfig != null) {
r.tmpConfig.setTo(r.newConfig);
if (r.overrideConfig != null) {
r.tmpConfig.updateFrom(r.overrideConfig);
}
if (DEBUG_CONFIGURATION) Slog.v(TAG, "Resuming activity "
+ r.activityInfo.name + " with newConfig " + r.tmpConfig);
performConfigurationChanged(r.activity, r.tmpConfig);
freeTextLayoutCachesIfNeeded(r.activity.mCurrentConfig.diff(r.tmpConfig));
r.newConfig = null;
}
if (localLOGV) Slog.v(TAG, "Resuming " + r + " with isForward="
+ isForward);
WindowManager.LayoutParams l = r.window.getAttributes();
if ((l.softInputMode
& WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION)
!= forwardBit) {
l.softInputMode = (l.softInputMode
& (~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION))
| forwardBit;
if (r.activity.mVisibleFromClient) {
ViewManager wm = a.getWindowManager();
View decor = r.window.getDecorView();
wm.updateViewLayout(decor, l);
}
}
r.activity.mVisibleFromServer = true;
mNumVisibleActivities++;
if (r.activity.mVisibleFromClient) {
r.activity.makeVisible();
}
}
if (!r.onlyLocalRequest) {
r.nextIdle = mNewActivities;
mNewActivities = r;
if (localLOGV) Slog.v(
TAG, "Scheduling idle handler for " + r);
Looper.myQueue().addIdleHandler(new Idler());
}
r.onlyLocalRequest = false;
// Tell the activity manager we have resumed.
if (reallyResume) {
try {
ActivityManagerNative.getDefault().activityResumed(token);//------ 1.4.6、此时Activity已经确定执行了完了onResume(),调用 ActivityManagerNative.getDefault().activityResumed(token) 通知AMS(通过binder跨进进程通信)把AMS中对应记录该Activity的状态更改为resumed,再次申明在AMS中保存的不是Activity只是该Activity的一个对应的数据结构(通过该token进行对应),其中记录了当前该Activity的相关状态信息,并进行维护。Activity生命周期的实现实际就是AMS对Activity的管理,根据逻辑在各个节点对这些<生命周期函数>的回调
} catch (RemoteException ex) {
}
}
} else {
// If an exception was thrown when trying to resume, then
// just end this activity.
try {
ActivityManagerNative.getDefault()
.finishActivity(token, Activity.RESULT_CANCELED, null, false);
} catch (RemoteException ex) {
}
}
}
@WindowManagerGloble.java WindowManagerGLoable是在WindowManagerImpl中初始化的其为全局单例类:WindowManagerGlobal.getInstance()
public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow) {
if (view == null) {
throw new IllegalArgumentException("view must not be null");
}
if (display == null) {
throw new IllegalArgumentException("display must not be null");
}
if (!(params instanceof WindowManager.LayoutParams)) {
throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");
}
final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
if (parentWindow != null) {
parentWindow.adjustLayoutParamsForSubWindow(wparams);
} else {
// If there's no parent, then hardware acceleration for this view is
// set from the application's hardware acceleration setting.
final Context context = view.getContext();
if (context != null
&& (context.getApplicationInfo().flags
& ApplicationInfo.FLAG_HARDWARE_ACCELERATED) != 0) {
wparams.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
}
}
ViewRootImpl root;
View panelParentView = null;
synchronized (mLock) {
// Start watching for system property changes.
if (mSystemPropertyUpdater == null) {
mSystemPropertyUpdater = new Runnable() {
@Override public void run() {
synchronized (mLock) {
for (int i = mRoots.size() - 1; i >= 0; --i) {
mRoots.get(i).loadSystemProperties();
}
}
}
};
SystemProperties.addChangeCallback(mSystemPropertyUpdater);
}
int index = findViewLocked(view, false);
if (index >= 0) {
if (mDyingViews.contains(view)) {
// Don't wait for MSG_DIE to make it's way through root's queue.
mRoots.get(index).doDie();
} else {
throw new IllegalStateException("View " + view
+ " has already been added to the window manager.");
}
// The previous removeView() had not completed executing. Now it has.
}
// If this is a panel window, then find the window it is being
// attached to for future reference.
if (wparams.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW &&
wparams.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
final int count = mViews.size();
for (int i = 0; i < count; i++) {
if (mRoots.get(i).mWindow.asBinder() == wparams.token) {
panelParentView = mViews.get(i);
}
}
}
root = new ViewRootImpl(view.getContext(), display);//----1.5.1、实例化ViewRootImpl,其中的参数包含了一个Display,这个是和View最终绘制有关
view.setLayoutParams(wparams);
mViews.add(view);//----1.5.2 在全局变量中添加记录该DecorView
mRoots.add(root);//----1.5.3 同时添加记录生成的ViewRoot
mParams.add(wparams);
}
// do this last because it fires off messages to start doing things
try {
root.setView(view, wparams, panelParentView);//----1.5.4绑定view到Root,使DecorView和ViewRootImpl相关联,至此ViewRootViewImpl中保存了DecorView的引用
} catch (RuntimeException e) {
// BadTokenException or InvalidDisplayException, clean up.
synchronized (mLock) {
final int index = findViewLocked(view, false);
if (index >= 0) {
removeViewLocked(index, true);
}
}
throw e;
}
}
@PhoneView.java
@Override
public void setContentView(int layoutResID) {
// Note: FEATURE_CONTENT_TRANSITIONS may be set in the process of installing the window
// decor, when theme attributes and the like are crystalized. Do not check the feature
// before this happens.
if (mContentParent == null) {
installDecor();//此处会生成DecoreView并会根据Theme和屏幕数据设置相关的参数,DecorView是一个FrameLayout。
} else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
mContentParent.removeAllViews();
}
if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
getContext());
transitionTo(newScene);
} else {
mLayoutInflater.inflate(layoutResID, mContentParent);//把我们在Activity中set的视图添加到CntentView位置
}
mContentParent.requestApplyInsets();
final Callback cb = getCallback();
if (cb != null && !isDestroyed()) {
cb.onContentChanged();
}
1.6.4.7 NativePreImeInputStage native的在调用到输入法之前的处理
@ViewRootImpl.java
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
synchronized (this) {
if (mView == null) {
mView = view;//------1.6.1此处即为DecorView,事件传递时,到达ViewRootImpl之后调用的即是DecorView的disPatchTouchEvent()
...
requestLayout();//===******===1.6.2请求布局开始,此处为View绘制的起始点
...
if (mInputChannel != null) {
if (mInputQueueCallback != null) {
mInputQueue = new InputQueue();
mInputQueueCallback.onInputQueueCreated(mInputQueue);
}
mInputEventReceiver = new WindowInputEventReceiver(mInputChannel,Looper.myLooper());//===******===1.6.3设置底层事件接收Receiver,此处是事件分发进入用户Application层的接入起始点
}
...
//------1.6.4、外部事件(点击,按键等)地处理Handler的初始化,以下构造的事件处理Handler是以单向链表的方式组织,处理是以职责链的方式进行处理
// Set up the input pipeline.
CharSequence counterSuffix = attrs.getTitle();
mSyntheticInputStage = new SyntheticInputStage();//----1.是一个兜底消息处理器,当前面的处理器都没有消费掉此次事件时最终会使用该处理器进行处理
InputStage viewPostImeStage = new ViewPostImeInputStage(mSyntheticInputStage);//----####---2.该消息处理器中会调用mView【DecorView】的dispatchTouchEvent()或Keyevent进行转发,进而进入到Activity,再回转到mDecorView
InputStage nativePostImeStage = new NativePostImeInputStage(viewPostImeStage,//----3.native的一个处理器 不太清楚是干什么的
"aq:native-post-ime:" + counterSuffix);
InputStage earlyPostImeStage = new EarlyPostImeInputStage(nativePostImeStage);//----4.输入法相关的拦截处理器,处理完后首先调用到的
InputStage imeStage = new ImeInputStage(earlyPostImeStage,
"aq:ime:" + counterSuffix);//----5.【和输入法相关的处理】相关的
InputStage viewPreImeStage = new ViewPreImeInputStage(imeStage);//----6.在在输入法处理之前调用,该处理中会回调所有View的dispatchKeyEventPreIme(event),进而调用onKeyPreIme()方法
InputStage nativePreImeStage = new NativePreImeInputStage(viewPreImeStage,
"aq:native-pre-ime:" + counterSuffix);-----7.native的在调用到输入法之前的处理
mFirstInputStage = nativePreImeStage;//---此处初始化后面事件处理时需要调用的mFirstInputStage
mFirstPostImeInputStage = earlyPostImeStage;//---此处初始化后面事件处理时需要调用的mFirstPostImeInputStage
mPendingInputEventQueueLengthCounterName = "aq:pending:" + counterSuffix;
}
}
}