一步步理解Android事件分发机制

Android事件分发机制 最近在学习安卓的事件分发机制,实际上到目前为止还没有写过自定义View,在自定义View中如果需要能够响应手指的点击或者滑动事件就需要处理事件的分发,否则很容易出现冲突。写这篇博客是为了让自己能够更好的消化吸收,同时以后忘了能够很快的捡回来。此篇主要参考。 阅读详情

回想一下,通常在Android开发中,我们最常接触到的是什么东西?显然除了Activity以外,就是各种形形色色的控件(即View)了。
与此同时,一个App诞生的起因,终究是根据不同需求完成与用户的各种交互。而所谓的交互,本质就是友好的响应用户的各种操作行为。
所以说,有很多时候,一个控件(View)出现在屏幕当中,通常不会是仅仅为了摆设,而是还要能够负责响应用户的操作。
以最基本的例子而言:现在某一个界面中有一个按钮(Button),而每当用户点击了该按钮,我们的程序将做出一定回应。
那么,如果我们还原“点击按钮”这一行为,可以视作其根本实际就是:用户的手指 与屏幕上该按钮所处的位置发生了某种接触。
所以简单来说,我们可以将用户每次与屏幕发生接触,视作是一次“触摸事件”。而对于每次“触摸事件”的回应处理,就构成了所谓的“交互”。
由此,也就引出了我们今天在此文里想要弄清楚的一个知识点,即“Android的事件分发机制”。接着,我们就一步一步的来走进它。

为什么需要分发?

在一切开始之前,我们先考虑一个问题。那就是为什么我们发现 关于这个知识点总是被描述为“事件分发”而不是“事件处理”?试想以下情况:

小明注册了一家公司开始了自己的创业之旅。这天,一位客户上门为小明的公司带来了第一单业务。我们可以将“这单业务”视作一次“触摸事件”。
小明乐坏了,赶紧开始着手这单业务。对应来说,我们可以理解为对“触摸事件”的处理。是的,目前为止我们都没发现任何和“分发”相关的东西。
其实,我们不难想象到之所以没有出现任何“分发”相关的东西,是因为现在公司只有小明独自一人,除了自己处理,他别无它选。
对于“分发”这个词本身就是以一定数量作为基础的。比如小明的公司经过发展扩大到了十个人的规模,划分了部门。这天又有新的业务来了。
这个时候小明就有很多选择了,他可以选择自己来处理这单业务;当然也可以选择将业务派发下去让员工来处理。这就是我们所谓的“分发”。

这个案例对应到Android中来说是一样的,如果我们能保证当前屏幕上永远只有唯一的一个View,那么对于“触摸事件”的处理就没什么好说的了。
但显然一个界面中通常都不会只有一个“独苗”,它会涉及到不定量的View(ViewGroup)的组合。这个时候当“事件”发生,就不那么容易处理了。
这其实也是为什么,“Android的事件分发机制”是我们从菜鸟到进阶的过程中绕不开必须掌握的一个知识点。
但实际上也没关系,当我们明白了“小明创业”的这个例子,实际也就已经掌握了关于事件分发最基本的原理。

看事件如何分发?

我们说了所有与用户发生交互的行为都是在手机屏幕,即某个界面中产生的。而Android的界面中的元素,无非就是View与ViewGroup。
与之同时,我们关注的另一个关键点是代表操作行为的“触摸事件”,这对应到英文中来说似乎就是“TouchEvent”。
OK,在我们目前两眼一抹瞎的情况下。不妨试着以“TouchEvent”为关键字,到View与ViewGroup类中去研究研究相关的方法。

最终,我们单独提出以下几个需要我们理解的方法,它们也是事件分发机制的原理所在:

  • dispatchTouchEvent
  • onTouchEvent
  • onInterceptTouchEvent (只存在于ViewGroup)

好的,截止现在我们还不太明白这几个方法的具体作用。只知道如果单独从命名上看,它们似乎分别代表分发、处理和拦截类似的作用。

起源在哪?

从现在开始,我们要正式的一步步研究一个触摸事件的处理过程。我们先来看一个十分基础但具有一定代表性的布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:tag="group_a"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <LinearLayout
        android:tag="group_b"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <Button
            android:tag="view"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

    </LinearLayout>
</LinearLayout>

但如果是这样,我们还是无法研究其事件的分发过程,所以我们自定义两个类分别继承LinearLayout以及Button类。
而我们要做的工作也很简单,就是在我们之前提及的与“事件分发”相关的方法中,分别加上类似如下的日志打印:

Log.d(getTag().toString(),”onTouchEvent”);

然后我们将布局文件中的LinearLayout和Button分别替换成我们自己定义的类,就搞定了。此时,我们运行程序后,对按钮进行点击,得到如下日志:

group_a: dispatchTouchEvent
group_a: onInterceptTouchEvent
group_b: dispatchTouchEvent
group_b: onInterceptTouchEvent
view: dispatchTouchEvent
view: onTouchEvent

一口气吃不成一个胖子,我们这里首先只关注一点,那就是:当我们点击按钮后,最先被触发的是“group_a“也就是最外层layout的dispatchTouchEvent方法。这个道理其实并不难理解,就像“小明创业”一样,如果一单业务来临,自然应该先由最高级别的“小明”知会。

也就是说,当一个“触摸事件”产生,将最先传送到最顶层View。这看上去合情合理,但我们又不难想到,如果谈到“最顶层”的话:
那么,我们所有的View,即我们整个布局文件,它实际也有一个载体,那就是它的宿主Activity。因为你一定记得”setContenView(R.layout.xxx)”。
那么,我们想象一下,“触摸事件”会不会最先被传送到Activity呢?打开Activity的源码我们惊喜的发现:它也包含dispatchTouchEvent和OnTouchEvent方法。OK,我们接着要做的,自然就是在我们的Activity类中覆写这两个方法,也加上日志打印,再次运行测试得到如下日志:

MainActivity: dispatchTouchEvent
group_a: dispatchTouchEvent
group_a: onInterceptTouchEvent
group_b: dispatchTouchEvent
group_b: onInterceptTouchEvent
view: dispatchTouchEvent
view: onTouchEvent

通过日志,我们不难发现,正如我们推测的一样,当触摸事件产生,的确是最先传递给Activity的。
这个时候,又要提到“小明”了。没错,当有业务来临,肯定是先到达“公司”层面,然后才是最高负责人“小明”。

打开Activity类的dispatchTouchEvent源码如下:

    public boolean dispatchTouchEvent(MotionEvent ev) {
        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
            onUserInteraction();
        }
        if (getWindow().superDispatchTouchEvent(ev)) {
            return true;
        }
        return onTouchEvent(ev);
    }

我们关注的重点放在下面一行代码上。由此,我们发现Activity接收到触摸事件后,是通过其所属的Window来分发事件的。

if (getWindow().superDispatchTouchEvent(ev))

Window自身是一个抽象类,而其superDispatchTouchEvent也是一个抽象方法。其唯一实现存在PhoneWindow类中。
而在PhoneWindow当中,superDispatchTouchEvent的实现是这样的:

    public boolean superDispatchTouchEvent(MotionEvent event){
        return mDecor.superDispatchTouchEvent(event);
    }

也就是,这时候事件的分发会传递到mDecor,即Android视图结构中所谓的“DecorView”当中,而DecorView自身本就是FrameLayout。
所以,这个时候事件分发的本质就很简单了,它回归到了FrameLayout,即ViewGroup的事件分发。

P.S: DecorView涉及到了Android的UI界面架构的知识。我们通常可以最简单的理解为一个Activiy就是一个界面。

但其实随着对Android越来越熟悉,我们也可以很容易猜测到,实际上肯定不仅仅如此。那么我们可以这样简单理解:

  • Activity会附属在PhoneWindow上;这其中会首先包裹一个DecorView(翻译就是装饰视图),它本身是一个FrameLayout。
    (所以,我们其实可以理解为,DecorView才是我们界面中真正位于最顶层的父View)
  • 而同时,通常来说,DecorView中会有两个子View,分别是:TitleView及ContentView。
  • 其中,TitleView简单来说就是我们平时所说的ActionBar(TitleBar)的那一列。而ContentView我们就熟悉了:“setContenView(R.layout.xxx)”

好了,话到这里,我们先对我们目前的收获进行总结,很简单:
当一个“触摸事件”产生,会首先传递到当前Activity。Activity会通过其所属Window,找到其中DecorView,从而开始逐级向下分发事件。

继续传递

回忆我们点击按钮时,所产生的输出日志:

MainActivity: dispatchTouchEvent
group_a: dispatchTouchEvent
group_a: onInterceptTouchEvent
group_b: dispatchTouchEvent
group_b: onInterceptTouchEvent
view: dispatchTouchEvent
view: onTouchEvent

我们发现,经由MainActivity进行传递,最终会首先到达该Activity的ContentView,即我们定义的布局文件中的最外层LinearLayou上。
这之后发生的事,我们通过日志观察的现象似乎是:事件在继续向下传递,直到最后到达了最里的Button,才通过onTouchEvent进行了处理。
所以,我们大胆猜测:一个“触摸事件”发生,会逐级dispatchTouchEvent,直至到达最底层的View,然后通过onTouchEvent进行处理。
这看上去是说得通的,但唯一的缺陷就在于,onInterceptTouchEvent 这个名字透露着拦截事件的方法,似乎并没有得到什么发挥?

那么,我们干脆直接打开ViewGroup中onInterceptTouchEvent的源码:

    public boolean onInterceptTouchEvent(MotionEvent ev) {
        return false;
    }

我们发现源码特别简单,唯一值得注意的是,该方法有一个布尔型的返回值,并且默认的返回值是false。
秉承着一贯的“手贱主义”的思想,我们将我们自定义的LinearLayou类中的onInterceptTouchEvent返回值修改为true。然后再次测试:

MainActivity: dispatchTouchEvent
group_a: dispatchTouchEvent
group_a: onInterceptTouchEvent
group_a: onTouchEvent

我们发现日志打印已经发生了改变,通过日志我们观察到的是:事件传递到group_a后不再向下传递了,直接通过group_a的onTouchEvent进行处理。
这一现象其实是合理的,它告诉了我们:onInterceptTouchEvent的返回结果将决定事件是否被拦截在当前View层面。返回true则拦截;否则继续传递。
而onInterceptTouchEvent的返回结果之所以能实现上述效果,可以在ViewGroup类中的dispatchTouchEvent方法里找到答案。
ViewGroup当中的dispatchTouchEvent源码很多,也很复杂,我们很难去读个透彻。但通过部分关键代码,我们可以知道它的原理是如下:
ViewGroup里,dispatchTouchEvent里会调用到onInterceptTouchEvent方法,并通过判断其返回结果决定下一步操作:

  • 如果onInterceptTouchEvent返回true,则会调用onTouchEvent方法处理触摸事件。
  • 如果onInterceptTouchEvent返回false,则会通过child.dispatchTouchEvent的形式向下分发事件。

到现在,看上去我们基本已经对事件的整个分发流程都触碰到了。但我们想象这样一种情况:
小明的公司接收了一单新的业务,并分发给了底下的小王去做。但这时候的问题可能是:
小王收到通知后发现自己完成不了。或者说小王给出了一套方案,但他对该方案的信心并不足。
这样的问题应该怎么解决,很显然,小王应该“报告老板”。这单业务最后的处理方案可能还是得您来拿。

这对应到我们的程序中,应该如何来实现呢?我们发现,onTouchEvent这个方法也有一个布尔型的返回值。
现在,我们试着将我们之前自定义的Button类里的onTouchEvent的返回值修改为固定返回false。再次运行程序测试:

MainActivity: dispatchTouchEvent
group_a: dispatchTouchEvent
group_a: onInterceptTouchEvent
group_b: dispatchTouchEvent
group_b: onInterceptTouchEvent
view: dispatchTouchEvent
view: onTouchEvent
group_b: onTouchEvent
group_a: onTouchEvent

我们发现,事件在经过button类里onTouchEvent处理后, 又回传到上层目录继续处理了。
由此我们可以知道:onTouchEvent的返回值也是另一种“拦截”,不同的是之前我们说的是拦截事件继续向下传递。
而这里,是在表明,这个事件“我”是否能够完全处理。如果能,则返回true,那么事件经过“我”处理后就结束了。否则返回false,再让父View去处理。

好了,这里我们先总结一下到目前为止,我们掌握到的关于事件分发机制的流程:

  • 当一个触摸事件产生,会首先传递到其所属Activity。Activity将负责将事件向下进行分发。
  • 该触摸事件将逐级的依次向下传递,直到传递至最底层View,然后进行处理。
  • ViewGroup在向下传递事件的时候,通过onInterceptTouchEvent的返回值来判断是否拦截事件。
  • 如果确定拦截事件,那么此次一系列的触摸事件都会通过该ViewGroup的onTouchEvent方法进行处理,并不再向下传递
  • onTouchEvent的返回结果决定了事件在此次处理之后,是否需要回传到上一级的View。

好了,我们继续看。我们肯定也注意到了,说了这么多,但我们之前关于事件分发的重点,都是放在上一层View向下层View分发事件的过程。
也就是说,之前我们的重点是在分析ViewGroup的dispatchTouchEvent方法,我们说了该方法会判断是否拦截事件,而决定是否继续向下传递事件。
当就拿我们此文中的例子来说,当事件最终传递到button类当中。我们不难想象到,这时dispatchTouchEvent的工作肯定与之前有所不同。
因为Button自身只是一个View,它不会存在所谓的子视图。也就说,这个时候事件你肯定要做出处理了,那么还分发个什么劲呢?

要得到这个问题的答案,最好的方式当然就是打开View类里的dispatchTouchEvent方法的源码看看,这里我们只截取我们关心的代码部分:

        if (onFilterTouchEventForSecurity(event)) {
            //noinspection SimplifiableIfStatement
            ListenerInfo li = mListenerInfo;
            if (li != null && li.mOnTouchListener != null
                    && (mViewFlags & ENABLED_MASK) == ENABLED
                    && li.mOnTouchListener.onTouch(this, event)) {
                result = true;
            }

            if (!result && onTouchEvent(event)) {
                result = true;
            }
        }

我们看到,首先会获取一个ListenerInfo类型的变量。该类型实际就是封装了各种类型的Listener。随后会开启第一次判断:
如果此对象不为空,mOnTouchListener不为空,且(mViewFlags & ENABLED_MASK) ==ENABLED,则会执行mOnTouchListener。
这其中(mViewFlags & ENABLED_MASK) ==ENABLED是判断控件状态是否是ENABLE的,默认情况肯定是的。
mOnTouchListener看着有些眼熟,如果我们查看源码,你就更眼熟了,因为我们发现它是通过如下代码进行赋值的:

    public void setOnTouchListener(OnTouchListener l) {
        getListenerInfo().mOnTouchListener = l;
    }

接着看代码,我们发现如果li.mOnTouchListener.onTouch(this, event)执行的结果也为true,那么result也将被设置为true。
假设该方法的执行结果返回是false,那么以上代码将继续进行,从而开始第二轮判断,于是onTouchEvent方法得以执行。

OK,对于这里的代码,我觉得有两点是值得一说的。第一是,我们首先可以明白如下的结论:

  • 假如我们为某个View设置了OnTouchListener,那么listener会先于onTouchEvent执行。同时:
  • 如果listener的onTouch方法返回true,那么onTouchEvent将不再执行。

第二点是,我们看到对于View来说:假设onTouchEvent的返回值为false,那么dispatchTouchEvent也会返回false。
这实际上就构成了整个“onTouchEvent返回值可以决定事件是否回传”的原因。这是因为:
ViewGroup在通过child.dispatchTouchEvent向下分发事件时,会通过该返回值来判断子视图是否具备处理事件的能力。
如果返回为false,就会继续遍历子视图,直至遍历到有一个具备事件处理能力的子视图为止。
如果没有一个具备处理能力的子视图,那么ViewGroup就会自己通过onTouchEvent来解决了。

到了这里,我们实际上已经对整个Android事件的分发机制有了不错的了解了。但我们肯定会想到一个问题:
那就是,以Button来说,我们通常是通过setOnClickListener的方式来对其设置点击事件监听的。
但很显然,我们目前为止研究过的代码中,还没有出现任何与之相关的东西。在View类中,我们剩下没有看过代码的,就是onTouchEvent了:

        if (((viewFlags & CLICKABLE) == CLICKABLE ||
                (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) ||
                (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE) {
            switch (action) {
                case MotionEvent.ACTION_UP:
                    boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
                    if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
                        // take focus if we don't have it already and we should in
                        // touch mode.
                        boolean focusTaken = false;
                        if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
                            focusTaken = requestFocus();
                        }

                        if (prepressed) {
                            // The button is being released before we actually
                            // showed it as pressed.  Make it show the pressed
                            // state now (before scheduling the click) to ensure
                            // the user sees it.
                            setPressed(true, x, y);
                       }

                        if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
                            // This is a tap, so remove the longpress check
                            removeLongPressCallback();

                            // Only perform take click actions if we were in the pressed state
                            if (!focusTaken) {
                                // Use a Runnable and post this rather than calling
                                // performClick directly. This lets other visual state
                                // of the view update before click actions start.
                                if (mPerformClick == null) {
                                    mPerformClick = new PerformClick();
                                }
                                if (!post(mPerformClick)) {
                                    performClick();
                                }
                            }
                        }

以上代码是我们关心的原因所在,我们看到经过一系列的判断后,会进入到一个名为performClick的方法调用,打开该方法的源码:

    public boolean performClick() {
        final boolean result;
        final ListenerInfo li = mListenerInfo;
        if (li != null && li.mOnClickListener != null) {
            playSoundEffect(SoundEffectConstants.CLICK);
            li.mOnClickListener.onClick(this);
            result = true;
        } else {
            result = false;
        }

        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
        return result;
    }

综合以上两段代码,我们可以得出以下结论:

  • onClickListener会在onTouchEvent方法中,ACTION为UP的时候得以执行。
  • 但注意前提条件是,控件是可点击(长按)的;并且mOnClickListener不为空。

最后的总结与比喻

最后,我们仍旧以“小明创业“的例子来总结我们所学到的关于Android的事件分发的相关知识。

  • 公司(Activity)接收了一项新的业务(触摸事件)。
  • 该业务会最先到达公司的最高层小明手上(最顶层View)。
  • 小明研究了以下此次业务,此时可以分为两种情况:
    1、小明认为此业务难度不大,于是决定将业务分配给部门经理小王(dispatch-event)。
    2、小明认为此次业务至关重要,决定自己处理(intercept-event & onTouchEvent)。
  • 假设业务分配给了经理小王,此时小王与小明一样,同样有两种选择:即自己拦截处理或者继续向下布置。
  • 业务最终终将被分配到某个员工的手中,它会负责处理(onTouchEvent)。
  • 但该员工接收到任务后,也可以判断自己是否能够完成,如果觉得不能完成,
    或者还需要上级审核,可以选择回报给上级(onTouchEvent返回false)
  • 员工处理该任务的方式也许有多种,例如A(OnTouchListener)、B(onTouchEvent)、C(OnClickListener) 等等。
    (它们的优先级顺序是 A > B > C 。。。。 )
Android 事件分发机制详解/ 及Activity启动流程浅谈 目前网上的事件分发机制文章很多,可能大家看了很多,还是很懵逼,这篇文章是我自己总结的事件分发机制,提取了在事件分发机制中,最精华的部分,如果对事件分发还是不太清楚,可以看看这篇文章。 阅读详情

相关推荐

Android 事件分发机制详解(上)

Android事件分发机制是Android开发者必须了解的基础。当一个点击事件发生时,从Activity的事件分发开始(主要包括:dispatchTouchEvent()、onTouchEvent() 总结如下:那么ViewGroup的什么时候返回true / false?请继续往下看ViewGroup事件的分发机制。Android事件分发传递到Acitivity后,总是先传递到ViewGroup、再传递到View。流程总结如下:(假设已经经过了Acitivity事件分发传递并传递到ViewGroup。

u010345983的博客 5263

Android事件分发机制详解:史上最全面、最易懂

点击事件由哪个对象发出,经过哪些对象,最终达到哪个对象并最终得到处理。这里的对象是指Activity、ViewGroup、View事件分发过程由dispatchTouchEvent() 、onInterceptTouchEvent()和onTouchEvent()三个方法协助完成经过上述3个问题,相信大家已经对Android的事件分发有了感性的认知,接下来,我将详细介绍Android事件分发机制。

w1142203475的博客 1万+

Android事件分发机制一:事件是如何到达activity的?

我们来回顾一下:DecorView交给Activity处理,Activity直接交给PhoneWindow处理,PhoneWindow直接交给其内部的DecorView处理,而DecorView则直接调用父类ViewGroup的方法进行分发,ViewGroup则会按照具体的逻辑分发到整个控件树中感兴趣的子控件。前面我们讲到,view树的根节点可以是一个viewGroup,也可以是一个单独的view,因此,这里的派发就会有两种不同的方式:直接给view进行处理 or viewGroup进行事件分发。

2501_90390274的博客 749

Android事件分发机制【最新、最全、最易懂、由浅入深】

Android事件分发流程 = Activity -> ViewGroup -> View即:1个点击事件发生后,事件先传到Activity、再传到ViewGroup、最终再传到ViewActivity对点击事件的分发机制ViewGroup对点击事件的分发机制View对点击事件的分发机制Activity事件分发机制、ViewGroup事件分发机制、View事件分发机制当一个点击事件发生时,从Activity的事件分发开始(),流程总结如下:三者介绍。

丨康有为丨的博客 1万+

【android Framework 探究】事件分发

Android 事件分发原理 闲暇时间,有空来整理一下android

lucky_tom的专栏 520

FreeModbus源码详解

本篇按照FreeModbus协议栈的工作流程,对源代码进行总结解析;FreeModbus协议栈作为从机,等待主机传送的数据,当从机接收到一帧完整的报文后,对报文进行解析,然后响应主机,发送报文给主机,实现主机和从机之间的通信; 1:demo.c中三个函数,完成协议栈的准备工作; eMBInit()函数:(mb.c) /*函数功能: *1:实现RTU模式和ASCALL模式的协议栈初始化; *2

2万+

「Android 事件分发机制」

「Android 事件分发机制」 一、事件分发机制 在Android体系中,事件分发机制占有重要的一份,了解事件的分发机制,对于滑动等冲突才有更深刻的理解。自定义View中能更好的扩展,遇到相关问题能从整个流程上思考,寻找最优解决办法。 一个简单的点击事件是怎样一步步被消费处理的呢?谁该处理,谁不该处理又是由什么因素决定的,这是在实际开发中绕不开的问题,尤其是在自定义View的应用场景下。 先上图,从整体上大致了解事件是怎样被传递与消费的: 二、从Activity开始 分析一个最简单的初始页面,

我有一壶酒,足以慰风尘 2186

YOLOv8实战:如何用Focaler-IoU提升小目标检测精度(附代码)

本文详细介绍了如何通过Focaler-IoU提升YOLOv8在小目标检测中的精度,包括核心机制解析、代码实现及调优策略。Focaler-IoU通过动态聚焦机制有效解决传统IoU对小目标检测的不足,显著提升模型性能。附有完整的代码示例和实战指南,适合计算机视觉开发者参考。

weixin_29044157的博客 362

带你从源码一步步分析Android View面试中的事件分发流程

在Android中,事件分发机制是一块很重要的知识点,掌握这个机制能帮你在平时的开发中解决掉很多的View事件冲突问题,这个问题也是面试中问的比较多的一个问题了,今天就来一探究竟

Mango先生的博客 1749

无刷电机FOC控制入门:磁场、洛伦兹力与坐标转换详解

本文深入解析无刷电机FOC(磁场定向控制)的核心原理,从电磁学基础的磁场与洛伦兹力出发,详细阐述了如何通过Clarke变换、Park变换等坐标转换技术,将三相交流解耦为直流量进行控制,最终利用SVPWM技术实现平滑、高效的电机驱动。文章旨在帮助开发者理解FOC的物理本质与数学框架,为机器人、无人机等高性能应用奠定基础。

weixin_29306011的博客 266

深入解析fio Benchmark测试:从源码到实践

本文深入解析fio Benchmark测试工具,从入门指南到源码架构分析,详细介绍了其核心模块、关键数据结构和I/O处理机制。通过实战案例展示如何优化存储性能测试,包括内存对齐、多线程调优等技巧,帮助开发者充分利用fio进行精准的存储性能评估。

weixin_42563415的博客 206

Android-事件分发机制源码详解

Android事件分发应该是每个Android开发人员必备的知识储备了。网上各个大神关于事件分发的文章非常多。本文尽量简单、详细、脉络清晰的思路来讲述事件分发机制。 最近也抽时间把Android的一些知识体系夯实,重新梳理一些Android的知识,后期会更新一些梳理的东西。 现在把事件分发机制重新梳理一遍,解决了一些之前疑惑的地方。 先问三个问题: 1 如果一个ViewGroup的onInterceptTouchEvent返回true,onTouchEvent返回false,事件会怎样传递? 2 手机屏

nyyin@qq.com 692

STM32CubeMX 6.4.0 + STM32F407ZGT6 实战:基于YT8512C PHY的lwIP以太网配置与调试

本文详细介绍了使用STM32CubeMX 6.4.0为STM32F407ZGT6微控制器配置YT8512C PHY芯片,并成功移植lwIP以太网协议栈的实战过程。文章从硬件差异分析入手,逐步讲解时钟配置、ETH外设设置、PHY寄存器适配以及lwIP协议栈剪裁等关键步骤,旨在帮助开发者解决非标准PHY芯片的联网难题,最终实现网络连通与Ping测试。

n8m7b6v5c4的博客 592

View的事件体系(三)view的事件分发机制

本章开始总结vie事件的分发机制:view的核心知识、view的难点、view的另一大难点滑动冲突解决的理论基础。 一、了解下 安卓的view层级: 其实我们平时在xml中写的view都是通过activity的setContentView被一步步加载到window上的,事件的产生也是首先从activity按照层级往下传递,一直到我们CustomView的最内层布局view,中间传递过程有着事...

dev晴天的博客 2100

在Jetson orin板卡上部署ocr模型遇到错误

摘要:安装ONNX Runtime GPU版本时遇到问题,直接pip install onnxruntime-gpu会报错。解决方案是从test.pypi.org下载对应的.whl文件(如ort_nightly-1.14.0...aarch64.whl),本地安装后还需降级NumPy版本(如pip install numpy==1.26),以解决NumPy版本兼容性问题。整个过程涉及三个关键步骤:下载正确架构的wheel文件、本地安装、调整NumPy版本。

xdxd3c的博客 1525

S32DS新建工程、编译调试下载、导入工程详细介绍

新建了一个工程之后,下面简单介绍下基本的UI界面。其中最左下角那个是界面,这个界面很重要,是图形化配置界面,然后可以根据这些配置自动生成代码。其中,左边那些配置文件,都是系统帮我们创建好了的,我们其实可以直接用就行。有PE工具的调试,以及Jlink工具的调试。我目前使用到PE工具调试可以查看寄存器值,而Jlink调试查看不了寄存器值。连接了开发板之后,点击Debug就可以吧程序下载到芯片上了,而且可以进入到调试界面。

luobeihai的博客 2万+

android按键事件分发,Android事件的分发机制详解

在分析Android事件分发机制前,明确android的两大基础控件类型:View和ViewGroup。View即普通的控件,没有子布局的,如Button、TextView. ViewGroup继承自View,表示可以有子控件,如Linearlayout、Listview这些。今天我们先来了解View的事件分发机制。先看下代码,非常简单,只有一个Button,分别给它注册了OnClick和OnTo...

weixin_42405371的博客 389

使用lightGBM进行数据建模及预测

在机器学习领域中,数据建模和预测一直是非常重要的任务。而lightGBM作为一种基于梯度提升算法的高效机器学习框架,被广泛应用于数据建模和预测中。本文将介绍如何使用lightGBM进行数据建模和预测。到此,我们已经成功使用lightGBM对数据进行了建模和预测。使用lightGBM可以快速、高效地完成数据建模和预测任务,是机器学习领域中不可或缺的工具之一。使用lightGBM进行数据建模及预测。

qq_37934722的博客 1016

Android一文让你轻松搞定Touch事件分发

什么是事件、相关Touch事件的方法、拥有上述事件的类、ViewGroup、View、事件分发流程、方法的简单用途解析。

帅次的博客 1153

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

Android事件分发完全解析之事件从何而来

上一节Android事件分发完全解析之为什么是她中我们简略地分析了事件分发机制的由来,这里要说明一点,Android(或者说任何的驱动系统)都包含大量不同类型的事件,比如按键啦、轨迹球啦、鼠标啦、触摸啦、红外线啦等等等,这里为了简化问题也为了切合实际,我们只针对触摸事件进行分析,至于其他的一些杂七杂八的事件其实都很好理解就不多说了。

AigeStudio 2万+

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

Android进阶-- Android事件分发机制

不同于前几篇文章的介绍,一步步的从调用到源码的去分析,关于Android事件分发机制,先明确一些概念,会更好理解。 1.事件分发从哪里开始,分发的又是什么? 事件分发从用户触摸屏幕开始,分发的是touch事件。 2.什么是touch事件? Touch事件也就是点击事件,touch事件将发生的位置、时间等封装成MotionEvent对象 3.MotionEvent 有四种类型,分别是: ...

sinat_33150417的博客 342

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

浅析安卓事件分发机制源码

最近工作需要需要做一些比较复杂的自定义View,其中事件分发的处理自然少不了,结合之前阅读过的大量资料,工作是完成了,但是对事件分发的处理总觉得很不清晰,知其然不知其所以然的感觉让人很不舒服。如果不知道事件分发原理,要是处理的情况很复杂的话,那就很难解决了。之前也看过任玉刚的《安卓开发艺术探索》对于事件分发源码的分析,但只能说大致了解了事件分发的流程,而不知其中的道理。 索性践行某位大师的名言—

易水南风的专栏 1096
上一篇: Java并发编程 - 逐级深入 看线程的中断
下一篇: 从源码一次彻底理解Android的消息机制
LaterEqualsNever
博客等级 码龄12年 297粉丝 61原创
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值