最近封裝一些功能性的jar包,因為需要產生一些動作,然後給調用者一些回調,所以用到了事件和監聽器。
舉個例子,比如DragListener和DragEvent,最開始寫的時候,每次Drag動作都觸發一個DragEvent事件,然後就得new一個DragEvent對象。後來感覺這樣太浪費記憶體了,然後就研究了一下系統的MotionEvent這個類,找到了好的
解決方案。
MotionEvent的構造方法是匿名的,不能直接建立,對外提供的擷取對象的介面是靜態obtain方法,可以從一個MotionEvent對象擷取,也可以從一些變數擷取。為什麼說它是個好的解決方案呢,因為它提供了一個recycle方法
,可以將當前的對象回收,下次要用的時候就不用重新再new一個新的對象了,直接從它的回收池裡面拿就行。
下面講解一下,MotionEvent裡面有幾個比較重要的變數,如下 :
Java代碼
- //變數
- 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;//回收棧的棧頂對象
//變數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代碼
- 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;
- }
- }
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代碼
- 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;
- }
- }
- }
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,同樣的回收原理,使得事件觸發頻繁的時候,大大的節約了記憶體的使用。