【Android】为啥事件传递这么频繁却不会造成内存抖动

学而不思则罔,思而不学则殆


引言

一般在Android开发中我们被要求说在onDraw方法不要新建对象,那为什么整体事件传递的时候,MotionEvent对象一直被回调,却没有造成内存波动,是为什么呢?

测试

针对这个问题,我专门做了测试,在dispatchTouchEvent方法中打印MotionEvent 对象的hashCode和信息。

测试代码

public class DiyView extends View{
    ...
    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        Log.d("zhangyu20201217", "dispatchTouchEvent:" + System.identityHashCode(event) + " " + event.hashCode() + " " + event);
        return super.dispatchTouchEvent(event);
    }
    ...

以下是测试结果:

测试一 两次手指按下起来

2020-12-17 08:01:21.457 18401-18401/com.example.viewtest D/zhangyu20201217: dispatchTouchEvent identityHashCode:154259924 hashCode:154259924 MotionEvent { action=ACTION_DOWN, actionButton=0, id[0]=0, x[0]=197.96436, y[0]=174.92969, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=39665544, downTime=39665544, deviceId=0, source=0x1002 }
2020-12-17 08:01:21.506 18401-18401/com.example.viewtest D/zhangyu20201217: dispatchTouchEvent identityHashCode:154259924 hashCode:154259924 MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=197.96436, y[0]=189.60889, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=4, eventTime=39665592, downTime=39665544, deviceId=0, source=0x1002 }
2020-12-17 08:01:21.531 18401-18401/com.example.viewtest D/zhangyu20201217: dispatchTouchEvent identityHashCode:154259924 hashCode:154259924 MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=194.96509, y[0]=199.68668, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=5, eventTime=39665614, downTime=39665544, deviceId=0, source=0x1002 }
2020-12-17 08:01:21.550 18401-18401/com.example.viewtest D/zhangyu20201217: dispatchTouchEvent identityHashCode:154259924 hashCode:154259924 MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=193.4578, y[0]=211.47052, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=4, eventTime=39665633, downTime=39665544, deviceId=0, source=0x1002 }
2020-12-17 08:01:21.569 18401-18401/com.example.viewtest D/zhangyu20201217: dispatchTouchEvent identityHashCode:154259924 hashCode:154259924 MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=188.96655, y[0]=223.7197, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=5, eventTime=39665651, downTime=39665544, deviceId=0, source=0x1002 }
2020-12-17 08:01:21.587 18401-18401/com.example.viewtest D/zhangyu20201217: dispatchTouchEvent identityHashCode:154259924 hashCode:154259924 MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=179.96875, y[0]=240.86429, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=7, eventTime=39665670, downTime=39665544, deviceId=0, source=0x1002 }
2020-12-17 08:01:21.604 18401-18401/com.example.viewtest D/zhangyu20201217: dispatchTouchEvent identityHashCode:154259924 hashCode:154259924 MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=171.245, y[0]=250.92578, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=5, eventTime=39665688, downTime=39665544, deviceId=0, source=0x1002 }
2020-12-17 08:01:21.622 18401-18401/com.example.viewtest D/zhangyu20201217: dispatchTouchEvent identityHashCode:154259924 hashCode:154259924 MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=165.96118, y[0]=260.61737, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=6, eventTime=39665707, downTime=39665544, deviceId=0, source=0x1002 }
2020-12-17 08:01:21.641 18401-18401/com.example.viewtest D/zhangyu20201217: dispatchTouchEvent identityHashCode:154259924 hashCode:154259924 MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=162.96191, y[0]=267.41992, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=3, eventTime=39665722, downTime=39665544, deviceId=0, source=0x1002 }
2020-12-17 08:01:21.689 18401-18401/com.example.viewtest D/zhangyu20201217: dispatchTouchEvent identityHashCode:154259924 hashCode:154259924 MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=162.96191, y[0]=268.97266, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=39665773, downTime=39665544, deviceId=0, source=0x1002 }
2020-12-17 08:01:21.690 18401-18401/com.example.viewtest D/zhangyu20201217: dispatchTouchEvent identityHashCode:154259924 hashCode:154259924 MotionEvent { action=ACTION_UP, actionButton=0, id[0]=0, x[0]=162.96191, y[0]=268.97266, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=39665779, downTime=39665544, deviceId=0, source=0x1002 }
2020-12-17 08:06:32.075 18401-18401/com.example.viewtest D/zhangyu20201217: dispatchTouchEvent identityHashCode:154259924 hashCode:154259924 MotionEvent { action=ACTION_DOWN, actionButton=0, id[0]=0, x[0]=294.96265, y[0]=259.94922, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=39976162, downTime=39976162, deviceId=0, source=0x1002 }
2020-12-17 08:06:32.124 18401-18401/com.example.viewtest D/zhangyu20201217: dispatchTouchEvent identityHashCode:154259924 hashCode:154259924 MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=294.96265, y[0]=262.9375, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=39976199, downTime=39976162, deviceId=0, source=0x1002 }
2020-12-17 08:06:32.140 18401-18401/com.example.viewtest D/zhangyu20201217: dispatchTouchEvent identityHashCode:154259924 hashCode:154259924 MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=297.9619, y[0]=270.37024, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=3, eventTime=39976221, downTime=39976162, deviceId=0, source=0x1002 }
2020-12-17 08:06:32.153 18401-18401/com.example.viewtest D/zhangyu20201217: dispatchTouchEvent identityHashCode:154259924 hashCode:154259924 MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=297.9619, y[0]=277.14856, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=2, eventTime=39976237, downTime=39976162, deviceId=0, source=0x1002 }
2020-12-17 08:06:32.179 18401-18401/com.example.viewtest D/zhangyu20201217: dispatchTouchEvent identityHashCode:154259924 hashCode:154259924 MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=297.9619, y[0]=283.97266, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=2, eventTime=39976253, downTime=39976162, deviceId=0, source=0x1002 }
2020-12-17 08:06:32.180 18401-18401/com.example.viewtest D/zhangyu20201217: dispatchTouchEvent identityHashCode:154259924 hashCode:154259924 MotionEvent { action=ACTION_UP, actionButton=0, id[0]=0, x[0]=297.9619, y[0]=283.97266, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=39976265, downTime=39976162, deviceId=0, source=0x1002 }

测试二 - 不同的页面测试

//AActivity.java
2020-12-17 08:24:16.497 19018-19018/com.example.viewtest D/zhangyu20201217: dispatchTouchEvent identityHashCode:267645040 hashCode:267645040 MotionEvent { action=ACTION_DOWN, actionButton=0, id[0]=0, x[0]=172.96875, y[0]=289.98047, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=41040583, downTime=41040583, deviceId=0, source=0x1002 }
2020-12-17 08:24:16.512 19018-19018/com.example.viewtest D/zhangyu20201217: dispatchTouchEvent identityHashCode:267645040 hashCode:267645040 MotionEvent { action=ACTION_UP, actionButton=0, id[0]=0, x[0]=172.96875, y[0]=289.98047, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=41040601, downTime=41040583, deviceId=0, source=0x1002 }

//BActivity.java
2020-12-17 08:24:49.738 19018-19018/com.example.viewtest D/zhangyu20201217: dispatchTouchEvent identityHashCode:267645040 hashCode:267645040 MotionEvent { action=ACTION_DOWN, actionButton=0, id[0]=0, x[0]=410.96558, y[0]=277.96875, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=41073821, downTime=41073821, deviceId=0, source=0x1002 }
2020-12-17 08:24:49.792 19018-19018/com.example.viewtest D/zhangyu20201217: dispatchTouchEvent identityHashCode:267645040 hashCode:267645040 MotionEvent { action=ACTION_UP, actionButton=0, id[0]=0, x[0]=410.96558, y[0]=277.96875, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=41073879, downTime=41073821, deviceId=0, source=0x1002 }

测试三 同一个应用杀进程测试

//杀进程前
2020-12-17 08:25:40.127 19175-19175/com.example.viewtest D/zhangyu20201217: dispatchTouchEvent identityHashCode:267645040 hashCode:267645040 MotionEvent { action=ACTION_DOWN, actionButton=0, id[0]=0, x[0]=366.96533, y[0]=380.97656, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=41124208, downTime=41124208, deviceId=0, source=0x1002 }
2020-12-17 08:25:40.216 19175-19175/com.example.viewtest D/zhangyu20201217: dispatchTouchEvent identityHashCode:267645040 hashCode:267645040 MotionEvent { action=ACTION_UP, actionButton=0, id[0]=0, x[0]=366.96533, y[0]=380.97656, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=41124276, downTime=41124208, deviceId=0, source=0x1002 }

//杀死进程后在启动测试
2020-12-17 08:26:55.298 19228-19228/com.example.viewtest D/zhangyu20201217: dispatchTouchEvent identityHashCode:267645040 hashCode:267645040 MotionEvent { action=ACTION_DOWN, actionButton=0, id[0]=0, x[0]=193.96362, y[0]=432.94922, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=41199384, downTime=41199384, deviceId=0, source=0x1002 }
2020-12-17 08:26:55.336 19228-19228/com.example.viewtest D/zhangyu20201217: dispatchTouchEvent identityHashCode:267645040 hashCode:267645040 MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=193.96362, y[0]=428.70605, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=1, eventTime=41199411, downTime=41199384, deviceId=0, source=0x1002 }
2020-12-17 08:26:55.360 19228-19228/com.example.viewtest D/zhangyu20201217: dispatchTouchEvent identityHashCode:267645040 hashCode:267645040 MotionEvent { action=ACTION_UP, actionButton=0, id[0]=0, x[0]=193.96362, y[0]=429.96094, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=41199450, downTime=41199384, deviceId=0, source=0x1002 }

测试四 不同进程

//com.example.viewtest进程
2020-12-17 08:39:09.508 19756-19756/com.example.viewtest D/zhangyu20201217: dispatchTouchEvent identityHashCode:149898054 hashCode:149898054 MotionEvent { action=ACTION_DOWN, actionButton=0, id[0]=0, x[0]=202.96143, y[0]=362.9297, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=41933595, downTime=41933595, deviceId=0, source=0x1002 }
2020-12-17 08:39:09.593 19756-19756/com.example.viewtest D/zhangyu20201217: dispatchTouchEvent identityHashCode:149898054 hashCode:149898054 MotionEvent { action=ACTION_UP, actionButton=0, id[0]=0, x[0]=202.96143, y[0]=362.9297, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=41933653, downTime=41933595, deviceId=0, source=0x1002 }

//com.example.tw进程
2020-12-17 08:39:48.327 19847-19847/com.example.tw D/zhangyu20201217: dispatchTouchEvent identityHashCode:139330987 hashCode:139330987 MotionEvent { action=ACTION_DOWN, actionButton=0, id[0]=0, x[0]=287.96265, y[0]=421.9336, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=41972412, downTime=41972412, deviceId=0, source=0x1002 }
2020-12-17 08:39:48.400 19847-19847/com.example.tw D/zhangyu20201217: dispatchTouchEvent identityHashCode:139330987 hashCode:139330987 MotionEvent { action=ACTION_UP, actionButton=0, id[0]=0, x[0]=287.96265, y[0]=421.9336, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=41972490, downTime=41972412, deviceId=0, source=0x1002 }

测试结果+总结

测试结果现象总结:

  1. 发现整个事件传递的流程中。【ACTION_DOWN】【ACTION_MOVE】【ACTION_UP】流中,MotionEvent 都是同一个对象。
  2. 就算不是同一个事件流,UP事件后再触发MotionEvent 跟之前还是同一个对象。
  3. 同一个进程不同页面间MotionEvent是同一个对象
  4. 同一进程后台杀死两次测试,MotionEvent是同一个对象
  5. 不同进程间的MotionEvent不是同一个对象

根据测试现象做结果分析:

  1. 同一个进程MotionEvent是同一个对象
  2. 不同进程MotionEvent不是同一个对象

源码分析

根据上面的测试,我们知道了在同一个进程中,MotionEvent是同一个对象。那么为什么?以及源码怎么实现的?
MotionEvent是同一个对象,我觉得,为了防止对象被重复创建,而且整个事件传递都是在主线程,不存在安全问题,只要每次事件源头同步好MotionEvent的状态就行。

根据源码:

    //MotionEvent.java
    private static final Object gRecyclerLock = new Object();
    private static int gRecyclerUsed;
    private static MotionEvent gRecyclerTop;
    ...
    private MotionEvent mNext;
    
    @UnsupportedAppUsage
    static private MotionEvent obtain() {
        final MotionEvent ev;
        synchronized (gRecyclerLock) {
            ev = gRecyclerTop;
            if (ev == null) {
                return new MotionEvent();
            }
            gRecyclerTop = ev.mNext;
            gRecyclerUsed -= 1;
        }
        ev.mNext = null;
        ev.prepareForReuse();
        return ev;
    }

MotionEvent.java中存在obtain方法(类似Handler的Message),该方法就是从缓存gRecyclerTop 中取出头部元素,没有就生成。然后gRecyclerTop 指向头部的下一个元素。等待下一次使用。而且gRecyclerTop是一个静态变量,在系统层面,是公用的。

    private static native long nativeInitialize(long nativePtr,
            int deviceId, int source, int displayId, int action, int flags, int edgeFlags,
            int metaState, int buttonState, @Classification int classification,
            float xOffset, float yOffset, float xPrecision, float yPrecision,
            long downTimeNanos, long eventTimeNanos,
            int pointerCount, PointerProperties[] pointerIds, PointerCoords[] pointerCoords);
            
    static public MotionEvent obtain(long downTime, long eventTime,
            int action, int pointerCount, PointerProperties[] pointerProperties,
            PointerCoords[] pointerCoords, int metaState, int buttonState,
            float xPrecision, float yPrecision, int deviceId,
            int edgeFlags, int source, int displayId, int flags) {
        MotionEvent ev = obtain();
        ev.mNativePtr = nativeInitialize(ev.mNativePtr,
                deviceId, source, displayId, action, flags, edgeFlags, metaState, buttonState,
                CLASSIFICATION_NONE, 0, 0, xPrecision, yPrecision,
                downTime * NS_PER_MS, eventTime * NS_PER_MS,
                pointerCount, pointerProperties, pointerCoords);
       ...
        return ev;
    }

还提供了native方法nativeInitialize,复用时去native层把属性重新赋值。

以上就是我的分析。很多问题需要从源码中找到解决办法和一些处理问题的思路。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值