Android系统事件的recycle原理

本文介绍了一种基于MotionEvent类的事件回收机制,该机制通过维护一个对象池来避免频繁创建和销毁事件对象,从而有效降低内存消耗。文章详细解释了MotionEvent类内部实现,包括obtain方法用于获取对象及recycle方法用于释放对象的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近封装一些功能性的jar包,因为需要产生一些动作,然后给调用者一些回调,所以用到了事件和监听器。

举个例子,比如DragListener和DragEvent,最开始写的时候,每次Drag动作都触发一个DragEvent事件,然后就得new一个DragEvent对象。后来感觉这样太浪费内存了,然后就研究了一下系统的MotionEvent这个类,找到了好的 解决方案。


MotionEvent的构造方法是匿名的,不能直接创建,对外提供的获取对象的接口是静态的obtain方法,可以从一个MotionEvent对象获取,也可以从一些变量获取。为什么说它是个好的解决方案呢,因为它提供了一个recycle方法
,可以将当前的对象回收,下次要用的时候就不用重新再new一个新的对象了,直接从它的回收池里面拿就行。

下面讲解一下,MotionEvent里面有几个比较重要的变量,如下

Java代码 复制代码 收藏代码
  1. //变量
  2. private MotionEvent mNext; //指向回收栈的下一个对象
  3. private boolean mRecycled; //标志是否是被回收掉的对象
  4. //静态变量
  5. static private final int MAX_RECYCLED = 10;//最大可回收的数目
  6. static private Object gRecyclerLock = new Object();//锁定整个类用的
  7. static private int gRecyclerUsed = 0;//回收栈中回收的对象数目
  8. static private MotionEvent gRecyclerTop = null;//回收栈的栈顶对象
//变量 private MotionEvent mNext; //指向回收栈的下一个对象 private boolean mRecycled; //标志是否是被回收掉的对象 //静态变量 static private final int MAX_RECYCLED = 10;//最大可回收的数目 static private Object gRecyclerLock = new Object();//锁定整个类用的 static private int gRecyclerUsed = 0;//回收栈中回收的对象数目 static private MotionEvent gRecyclerTop = null;//回收栈的栈顶对象

然后有一个静态的obtain方法:

Java代码 复制代码 收藏代码
  1. static private MotionEvent obtain() {
  2. synchronized (gRecyclerLock) { //锁住整个类
  3. if (gRecyclerTop == null) {//栈顶不存在,就new一个新的
  4. return new MotionEvent();
  5. }
  6. MotionEvent ev = gRecyclerTop;//栈顶存在,就用一个引用ev指向它
  7. gRecyclerTop = ev.mNext;//然后把栈顶的下一个对象提到栈顶
  8. gRecyclerUsed--;//回收栈中的对象数目减少一个
  9. ev.mRecycledLocation = null;//是一个异常,作用未知
  10. ev.mRecycled = false;//当前对象标志为未回收状态
  11. return ev;
  12. }
  13. }
static private MotionEvent obtain() { synchronized (gRecyclerLock) { //锁住整个类 if (gRecyclerTop == null) {//栈顶不存在,就new一个新的 return new MotionEvent(); } MotionEvent ev = gRecyclerTop;//栈顶存在,就用一个引用ev指向它 gRecyclerTop = ev.mNext;//然后把栈顶的下一个对象提到栈顶 gRecyclerUsed--;//回收栈中的对象数目减少一个 ev.mRecycledLocation = null;//是一个异常,作用未知 ev.mRecycled = false;//当前对象标志为未回收状态 return ev; } }

其它几个obtain方法都首先调用obtain()方法从回收栈中获取对象,然后赋值。

它的recycle方法如下:

Java代码 复制代码 收藏代码
  1. public void recycle() {
  2. // 确保recycle方法只调用一次
  3. if (TRACK_RECYCLED_LOCATION) {
  4. if (mRecycledLocation != null) {
  5. throw new RuntimeException(toString() + " recycled twice!", mRecycledLocation);
  6. }
  7. mRecycledLocation = new RuntimeException("Last recycled here");
  8. } else if (mRecycled) {
  9. throw new RuntimeException(toString() + " recycled twice!");
  10. }
  11. synchronized (gRecyclerLock) {//锁住类
  12. if (gRecyclerUsed < MAX_RECYCLED) { //如果回收栈中的对象还没达到最大值
  13. gRecyclerUsed++; //回收栈中元素数目增加1
  14. mNumHistory = 0;
  15. //这两句是把当前对象的next指向以前的栈顶,然后把当前对象放到栈顶
  16. mNext = gRecyclerTop;
  17. gRecyclerTop = this;
  18. }
  19. }
  20. }
public void recycle() { // 确保recycle方法只调用一次 if (TRACK_RECYCLED_LOCATION) { if (mRecycledLocation != null) { throw new RuntimeException(toString() + " recycled twice!", mRecycledLocation); } mRecycledLocation = new RuntimeException("Last recycled here"); } else if (mRecycled) { throw new RuntimeException(toString() + " recycled twice!"); } synchronized (gRecyclerLock) {//锁住类 if (gRecyclerUsed < MAX_RECYCLED) { //如果回收栈中的对象还没达到最大值 gRecyclerUsed++; //回收栈中元素数目增加1 mNumHistory = 0; //这两句是把当前对象的next指向以前的栈顶,然后把当前对象放到栈顶 mNext = gRecyclerTop; gRecyclerTop = this; } } }

根据这个思路,我也做了一个Event,同样的回收原理,使得事件触发频繁的时候,大大的节约了内存的使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值