android的点击事件,Android中点击事件的来源

本文主要分析Android中点击事件的来源,从Activity启动创建Window和WindowManager,到设置布局、关联Window和DecorView、注册InputChanel,再到接收和传递点击事件等过程,着重分析了Java代码,如Activity的attach方法、Instrumentation调用Activity的onCreate方法等。

本文将分以下在步骤寻找android中事件的来源:

一、activity启动时 创建window以及windowManager的过程。

二、调用setContentView设置布局的过程

三、Activity在onResume之后创建ViewRootImp将window和DecorView关联的过程

四、创建InputChanel 发送给InputManagerService进行注册的过程

五、WindowInputEventReceiver 接受到点击事件传递到Actvity的过程。

六、Activity将事件传递给view的过程。

对于底层c++代码如何使用inputChannel来传递事件,目前小弟不懂,所有不敢胡诌邹。所以本文只分析java代码。

下面进入正文:

一、activity启动之后发生了什么?

activity启动将调用很多方法,本文我们着重看activity的 attach方法(即创建window,和windowManager的发法)。

我们直接从 ActivityThread的 handleLaunchActivity开始看吧。

private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {

...

Activity a = performLaunchActivity(r, customIntent);

if (a != null) {

r.createdConfig = new Configuration(mConfiguration);

Bundle oldState = r.state;

handleResumeActivity(r.token, false, r.isForward,

!r.activity.mFinished && !r.startsNotResumed);

可以看到先调用了 performLaunchActivity,在这个方法之后会调用handleResumeActivity,从名字上可以大概猜出来handleResumeActivity 最终会执行activiyt的onResume方法。我们先分析第一个方法performLaunchActivity,看看它到底怎么启动。

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {

...

Activity activity = null;

try {

//使用反射创建activity

java.lang.ClassLoader cl = r.packageInfo.getClassLoader();

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);

}

}

...

//调用activity 的attach方法

activity.attach(appContext, this, getInstrumentation(), r.token,

r.ident, app, r.intent, r.activityInfo, title, r.parent,

r.embeddedID, r.lastNonConfigurationInstances, config,

r.voiceInteractor);

if (customIntent != null) {

activity.mIntent = customIntent;

}

r.lastNonConfigurationInstances = null;

activity.mStartedActivity = false;

int theme = r.activityInfo.getThemeResource();

if (theme != 0) {

activity.setTheme(theme);

}

activity.mCalled = false;

if (r.isPersistable()) {

//最终会执行activity的 onCreate方法

mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);

} else {

mInstrumentation.callActivityOnCreate(activity, r.state);

}

ok,这里只要有3块,第一块很容易看出来 是使用反射创建Activity的实例

第二块是调用 activity的attach我们一会着重看一下,第三块是使用Instrumentation执行一个犯法,这个方法最终会走activiy.onCreate(),

我们先看 第三块吧:

Instrumentation.java

public void callActivityOnCreate(Activity activity, Bundle icicle,

PersistableBundle persistentState) {

prePerformCreate(activity);

activity.performCreate(icicle, persistentState);

postPerformCreate(activity);

}

activity.java

final void performCreate(Bundle icicle, PersistableBundle persistentState) {

restoreHasCurrentPermissionRequest(icicle);

//调用activity的 onCreate

onCreate(icicle, persistentState);

mActivityTransitionState.readState(icicle);

performCreateCommon();

}

好了,第三块就看完了。这下来看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) {

attachBaseContext(context);

mFragments.attachHost(null /*parent*/);

//这里直接new PhoneWindow 我贴出的是6.0 的代码

//5.0 这块是 mWindow = PolicyManager.makeNewWindow(this);

//实质是一样的。

mWindow = new PhoneWindow(this);

//给window 设置callback ,最后分发事件的时候 会回调

//因为activity刚好实现了 callback接口,decorView最后会回调它,将事件传给activity

mWindow.setCallback(this);

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());

}

}

//设置windowManager,其实他的实现是windowManagerImpl

mWindow.setWindowManager(

(WindowManager)context.getSystemService(Context.WINDOW_SERVICE),

mToken, mComponent.flattenToString(),

(info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);

if (mParent != null) {

mWindow.setContainer(mParent.getWindow());

}

mWindowManager = mWindow.getWindowManager();

mCurrentConfig = config;

}

(责任编辑:ioter)

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值