• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >Android > Android中MotionEvent的来源和ViewRootImpl

Android中MotionEvent的来源和ViewRootImpl

作者:网友 字体:[增加 减小] 来源:互联网 时间:2017-05-26

网友通过本文主要向大家介绍了android viewrootimpl,viewrootimpl,android motionevent,android中motionevent,leap motion android等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

Android中MotionEvent的来源和ViewRootImpl


前言

很久没有发表文章了,今天来一篇,大家撒花~~~

本文打算分析下Android中点击事件的来源,顺便提及下ViewRootImpl。

Android中点击事件的来源

这个问题,也许你会说“这还用你说吗?我可是看过艺术探索的人”,我知道艺术探索中的确是详细介绍了点击事件的传递流程,反正大致就是点击事件从Activity传递给PhoneWindow,然后PhoneWindow再传递给DecorView,接着DecorView就进行后续的遍历式的传递。这都没错,但是点击事件是谁传递给Activity的呢?这个大家可能不清楚吧?那本文就是分析这个问题的。

首先看Activity的实现,如下,Activity实现了一个特殊的接口:Window.Callback。

public class Activity extends ContextThemeWrapper
        implements LayoutInflater.Factory2,
        Window.Callback, KeyEvent.Callback,
        OnCreateContextMenuListener, ComponentCallbacks2,
        Window.OnWindowDismissedCallback {
    private static final String TAG = "Activity";
    private static final boolean DEBUG_LIFECYCLE = false;

那么Window.Callback到底是什么东西呢?如下:

    /**
     * API from a Window back to its caller.  This allows the client to
     * intercept key dispatching, panels and menus, etc.
     */
    public interface Callback {
        /**
         * Called to process key events.  At the very least your
         * implementation must call
         * [email protected] android.view.Window#superDispatchKeyEvent} to do the
         * standard key processing.
         *
         * @param event The key event.
         *
         * @return boolean Return true if this event was consumed.
         */
        public boolean dispatchKeyEvent(KeyEvent event);

        /**
         * Called to process touch screen events.  At the very least your
         * implementation must call
         * [email protected] android.view.Window#superDispatchTouchEvent} to do the
         * standard touch screen processing.
         *
         * @param event The touch screen event.
         *
         * @return boolean Return true if this event was consumed.
         */
        public boolean dispatchTouchEvent(MotionEvent event);

        /**
         * Called to process trackball events.  At the very least your
         * implementation must call
         * [email protected] android.view.Window#superDispatchTrackballEvent} to do the
         * standard trackball processing.
         *
         * @param event The trackball event.
         *
         * @return boolean Return true if this event was consumed.
         */
        public boolean dispatchTrackballEvent(MotionEvent event);
        ...(省略若干代码,下同)

然后我们似乎看出了一些端倪,难道这个接口和点击事件的传递有关?嗯,你猜对了。在艺术探索这本书中,并没有描述事件是如何传递给Activity的,但是这里我们可以猜测,如果外界想要传递点击事件给Activity,那么它就必须持有Activity的引用,这没错,在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*/);

        mWindow = new PhoneWindow(this);
        mWindow.setCallback(this);
        mWindow.setOnWindowDismissedCallback(this);
        mWindow.getLayoutInflater().setPrivateFactory(this);

显然,mWindow持有了Activity的引用,它通过setCallback方法来持有Activity,因此,事件是从Window传递给了Activity。也许你会说:“我不信,这理由不充分!”,没关系,我们继续分析。

我们知道,Activity启动以后,在它的onResume以后,DecorView才开始attach给WindowManager从而显示出来。(什么?你不知道?回去看艺术探索第8章),请看Activity的makeVisible方法,代码如下:

    void makeVisible() {
        if (!mWindowAdded) {
            ViewManager wm = getWindowManager();
            wm.addView(mDecor, getWindow().getAttributes());
            mWindowAdded = true;
        }
        mDecor.setVisibility(View.VISIBLE);
    }

接着,系统就会完成添加Window的过程,看WindowManagerGlobal的addView方法,如下:

    public void addView(View view, ViewGroup.LayoutParams params,
            Display display, Window parentWindow) {
        ViewRootImpl root;
        View panelParentView = null;
        ...这里省略了一堆代码
        root = new ViewRootImpl(view.getContext(), display);
        view.setLayoutParams(wparams);
        mViews.add(view);
        mRoots.add(root);
        mParams.add(wparams);

        // do this last because it fires off messages to start doing things
        try {
            root.setView(view, wparams, panelParentView);
        } catch (RuntimeException e) {
            // BadTokenException or InvalidDisplayException, clean up.
            synchronized (mLock) {
                final int index = findViewLocked(view, false);
                if (index >= 0) {
                    removeViewLocked(index, true);
                }
            }
            throw e;
        }
    }

可以看到,ViewRootImpl创建了,在ViewRootImpl的setView方法(此方法运行在UI线程)中,会通过跨进程的方式向WMS(WindowManagerService)发起一个调用,从而将DecorView最终添加到Window上,在这个过程中,ViewRootImpl、DecorView和WMS会彼此向关联,同时会创建InputChannel、InputQueue和WindowInputEventReceiver来接受点击事件的消息。

好了,言归正传,下面来说,点击事件到底怎么传递给Activity的。首先要明白,点击事件是由用户的触摸行为所产生的,因此它必须要通过硬件来捕获,然后点击事件会交给WMS来处理。

在ViewRootImpl中,有一个方法,叫做dispatchInputEvent,如下:

    public void dispatchInputEvent(InputEvent event, InputEventReceiver receiver) {
        SomeArgs args = SomeArgs.obtain();
        args.arg1 = event;
        args.arg2 = receiver;
        Message msg = mHandler.obtainMessage(MSG_DISPATCH_INPUT_EVENT, args);
        msg.setAsynchronous(true);
        mHandler.sendMessage(msg);
    }

那么什么是InputEvent呢?InputEvent有2个子类:KeyEvent和MotionEvent,其中KeyEvent表示键盘事件,而MotionEvent表示点击事件。在上面的代码中,mHandler是一个在UI线程创建的Handder,所以它会把执行逻辑切换到UI线程中。

    final ViewRootHandler mHandler = new ViewRootHandler();

这个消息的处理如下:

            case MSG_DISPATCH_INPUT_EVENT: {
                SomeArgs args = (SomeArgs)msg.obj;
                InputEvent event = (InputEvent)args.arg1;
                InputEventReceiver receiver = (InputEventReceiver)args.arg2;
                enqueueInputEvent(event, receiver, 0, true);
                args.recycle();
            }

除此之外,WindowInputEventReceiver也可以来接收点击事件的消息,同样它也有一个dispatchInputEvent方法,注意,WindowInputEventReceiver中的Looper为UI线程的Looper。

    mInputEventReceiver = new WindowInputEventReceiver(mInputChannel,
             Looper.myLooper());

    // Called from native code.
    @SuppressWarnings("unused")
    private void dispatchInputEvent(int seq, InputEvent event) {
        mSeqMap.put(event.getSequenceNumber(), seq);
        onInputEvent(event);
    }

    @Override
    public void onInputEvent(InputEvent event) {
        enqueueInputEvent(event, this, 0, true);
    }

可以发现,不管是ViewRootImpl的dispatchInputEv

分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • Android中MotionEvent的来源和ViewRootImpl

相关文章

  • 2017-05-26认识Activity,创建第一个android应用,activityandroid
  • 2017-05-26安卓第十四天笔记-内容提供者(ContentProvider),contentprovider
  • 2017-05-26浅谈Android应用保护(一):Android应用逆向的基本方法,浅谈android
  • 2017-05-26RecyclerView再封装,RecyclerView封装
  • 2017-05-26BottomBar之Android底部菜单,bottombarandroid
  • 2017-05-26AndroidTV版(乐视超3 X55)root,将自己的软件设置为开机自启、系统软件,卸载系统应用等问题总结,androidtvx55
  • 2017-05-26安卓四大组件之内容提供者,安卓四大提供者
  • 2017-05-26ViewPager结合view无限滑动,viewpagerview滑动
  • 2017-05-26安卓开源项目周报0329,安卓开源项目0329
  • 2017-05-26[Android]Android布局优化之<include />,androidinclude

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • 高效地分析Android内存--MAT工具解析
    • android开发之路11(用SharedPreferences存储数据),sharedpreferences
    • UI-初识君面之理论篇,ui-初识理论篇
    • 7.4 Android 调用 WebService
    • PostgreSQL空值null参与运算的处理方法
    • Android 手机卫士--参照文档编写选择器,android选择器
    • Android,androidstudio
    • 注册时获取验证码常用的倒计时工具,注册时验证码
    • [android] 手机卫士设备管理权限锁屏,android锁屏
    • 编译android源码3---ubuntu安装jdk6

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有