代码改变世界

Android系统事件的recycle原理

2010-07-25 21:08  $等待$  阅读(4055)  评论(1编辑  收藏  举报

最近封装一些功能性的jar包,因为需要产生一些动作,然后给调用者一些回调,所以用到了事件和监听器。 
举个例子,比如DragListener和DragEvent,最开始写的时候,每次Drag动作都触发一个DragEvent事件,然后就得new一个DragEvent对象。后来感觉这样太浪费内存了,然后就研究了一下系统的MotionEvent这个类,找到了好的 解决方案。

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

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

 

代码
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;//回收栈的栈顶对象

 

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

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

      它的recycle方法如下:

代码
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 }

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

      它的recycle方法如下:

代码
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
12 synchronized (gRecyclerLock) {//锁住类
13 if (gRecyclerUsed < MAX_RECYCLED) { //如果回收栈中的对象还没达到最大值
14 gRecyclerUsed++; //回收栈中元素数目增加1
15 mNumHistory = 0;
16 //这两句是把当前对象的next指向以前的栈顶,然后把当前对象放到栈顶
17 mNext = gRecyclerTop;
18 gRecyclerTop = this;
19 }
20 }
21 }
22

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