Android系統事件的recycle原理

來源:互聯網
上載者:User

最近封裝一些功能性的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.  
  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.     } 
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,同樣的回收原理,使得事件觸發頻繁的時候,大大的節約了記憶體的使用。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.