android点击事件在activity中的传递流程

概述

当手指点击屏幕时候,linux就会接收到对应的事件中断,然后将这些中断事件包装成输入事件写入到相应的设备节点中,android输入系统所进行的操作大致来说就是监控这些设备节点,当有数据可读时候就读取这些数据,将其翻译成点击事件,然后寻找到合适的窗口,将其派发下去。

一个点击事件的传递流程

当产生一个点击事件后,首先在ViewRootImpl的WindowInputEventReceiver中接收到事件,然后将其传递到DecorView中,在activity中绕一圈继续回到DecorView开始真正的向下级控件传递,通过层层ViewGroup的传递最终到达View中,如果在ViewGroup中被拦截,或者传递到了View中,但是View并没有处理消费这次点击事件,就会层层返回false,最终在回到activity中,由activity调用activity中的onTouchEvent消费本次点击事件,流程如下图:
在这里插入图片描述
WindowInputEventReceiver的初始化

WindowInputEventReceiver继承自InputEventReceiver,用于接收从输入管理系统派发来的点击事件,在acivity界面显示过程中被初始化,其初始化过程如下图:
在这里插入图片描述
下是依据流程图中的具体代码细节截取:

ActivityThread.java

    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        ......
        初始化activity
        try {
            java.lang.ClassLoader cl = appContext.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) {
            ...
        }

        try {
            
                ......
                调用attach,在其中进行窗口、窗口管理、回调的初始化
                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, window, r.configCallback);

                ......
    }
Activity.java

    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, ActivityConfigCallback activityConfigCallback) {
    
        初始化mWindow、设置回调,初始化WindowManager
        mWindow = new PhoneWindow(this, window, activityConfigCallback);
        mWindow.setWindowControllerCallback(this);
        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();

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

        mWindow.setColorMode(info.colorMode);

    }

attach运行完成会回到activity中的OnCreate

                if (r.isPersistable()) {
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                } else {
                    mInstrumentation.callActivityOnCreate(activity, r.state);
                }

在oncreate中会进行界面布局文件的设置setContentView

    public void setContentView(@LayoutRes int layoutResID) {
        getWindow().setContentView(layoutResID);
        initWindowDecorActionBar();
    }

PhoneWindow中主要进行DecorView和mContentParent的初始化,和布局文件的inflate操作

    public void setContentView(int layoutResID) {

        if (mContentParent == null) {
        初始化mDecor和mContentParent
            installDecor();
        } 

        ......
        解析布局,添加到mContentParent中
            mLayoutInflater.inflate(layoutResID, mContentParent);
        }
        ......
    }

布局文件解析完成后,会在ActivityThread中进入handleResumeActivity,在这里会完成布局文件的显示

    @Override
    public void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward,
            String reason) {
        ......
        
        if (r.window == null && !a.mFinished && willBeVisible) {
            r.window = r.activity.getWindow();
            View decor = r.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;
              
                ViewRootImpl impl = decor.getViewRootImpl();
                if (impl !&
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值