Android遊戲開發架構(三)記憶體回收行程

來源:互聯網
上載者:User

以下均轉自Android遊戲編程入門經典,轉載請標明出處

對於Android開發人員來說,什麼是最糟糕的事情?讓一切工作都停止啟動並執行記憶體回收!

我們先來看看Input介面

package org.example.androidgames.framework;import java.util.List;public interface Input {    public static class KeyEvent {        public static final int KEY_DOWN = 0;        public static final int KEY_UP = 1;        public int type;        public int keyCode;        public char keyChar;        public String toString() {            StringBuilder builder = new StringBuilder();            if (type == KEY_DOWN)                builder.append("key down, ");            else                builder.append("key up, ");            builder.append(keyCode);            builder.append(",");            builder.append(keyChar);            return builder.toString();        }    }    public static class TouchEvent {        public static final int TOUCH_DOWN = 0;        public static final int TOUCH_UP = 1;        public static final int TOUCH_DRAGGED = 2;        public int type;        public int x, y;        public int pointer;        public String toString() {            StringBuilder builder = new StringBuilder();            if (type == TOUCH_DOWN)                builder.append("touch down, ");            else if (type == TOUCH_DRAGGED)                builder.append("touch dragged, ");            else                builder.append("touch up, ");            builder.append(pointer);            builder.append(",");            builder.append(x);            builder.append(",");            builder.append(y);            return builder.toString();        }    }    public boolean isKeyPressed(int keyCode);    public boolean isTouchDown(int pointer);    public int getTouchX(int pointer);    public int getTouchY(int pointer);    public float getAccelX();    public float getAccelY();    public float getAccelZ();    public List<KeyEvent> getKeyEvents();    public List<TouchEvent> getTouchEvents();}

我們從定義兩個類開始,KeyEvent和TouchEvent。KeyEvent類定義了一些該常量類型,TouchEvent也是一樣。當事件類型為KEY_UP時,一個KeyEvent執行個體將會記錄它的類型、按鍵代碼和Unicode字元。

TouchEvent的代碼也很相似,它定義了TouchEvent事件類型、觸點相對於UI組件原點的位置和觸控螢幕的驅動程式賦予手指的指標ID。只要手指還在螢幕上,那麼它的指標ID是不會變的。如果按下了兩隻手指,那麼當手指0離開時,手指1會保持其ID不變直到它離開觸控螢幕。當一個新的手指按下時會得到第一個未佔用的ID,本例中將會得到0。指標ID通常是按順序分配的,但是並不保證一定如此。

接下來便是Input介面的輪詢方法,其用途很明顯。Input.isKeyPressed()接受一個keyCode參數,並返回對應當前按鍵是否被按下資訊。Input.isTouchDown()、Input.getTouchX()和Input.getTouchY()返回是否按下一個給定的指標,以及其當前的x和y座標。注意,如果實際上相應的指標沒有觸控螢幕幕的話,其座標是沒法確定的。

Input.getAccelX()、Input.getAccelY()、Input.getAccelZ()返回加速計在各個軸上的值。

最後兩個方法用於基於事件的處理,它將返回上次我們調用這些方法後所記錄的KeyEvent和TouchEvent執行個體。該事件按發生時間排序,最新發生的事件排在列表的最後面。

現在回到記憶體回收行程設計上來,在Input介面裡getTouchEvents()和getKeyEvents()方法。它將返回TouchEvent和KeyEvent列表。在鍵盤和觸摸事件處理常式中,我們將不斷建立這兩個類的執行個體,並將它們儲存在內部處理常式的列表中。當一個鍵被按下或手指觸控螢幕幕時,Android的輸入系統會觸發很多事件。所以我們會不斷建立新執行個體,在很短的時間間隔內,這些事件會被記憶體回收行程收集。為了避免這種情況,我們將實現一個稱之為實力入池(instance
pooling)的概念。它不是在一個類中不斷地建立新執行個體,而是簡單地重用以前的執行個體。Pool類是實現這種行為的一種很便捷的方式。

package org.example.androidgames.framework;import java.util.ArrayList;import java.util.List;public class Pool<T> {private final List<T> freeObjects;private final PoolObjectFactory<T> factory;private final int maxSize;public interface PoolObjectFactory<T>{public T createObject();}public Pool(PoolObjectFactory<T> factory, int maxSize){this.factory = factory;this.maxSize = maxSize;this.freeObjects =new ArrayList<T>(maxSize);}public T newObject(){T object = null;if(freeObjects.size() == 0)object = factory.createObject();elseobject = freeObjects.remove(freeObjects.size() - 1);return object;}public void free(T object){if(freeObjects.size() < maxSize)freeObjects.add(object);}}

Pool<T>這裡使用了泛型。這個類是個通用類型的類,泛型允許我們在Pool類中儲存任何類型的對象,而無須對類型進行轉換。

首先定義的是一個名為PoolObjectFactory的介面,它是泛型的。它只有一個方法createObject(),該方法將返回一個新對象,其具有泛型型別的Pool/PoolObjectFactory執行個體。

Pool類有3個成員:ArrayList用於儲存以入池的對象,PoolObjectFactory用於產生Pool類中包含的類型的新執行個體,第三個成員用於存放Pool可以容納的最大對象數量。最後一個成員是必需的,這樣Pool才不會無限制增長;否則,我們將可能會遇到一個記憶體耗盡的異常。

Pool類的建構函式接受一個PoolObjectFactory和所儲存物件的最大數量。這兩個參數都儲存在各自的成員變數裡,並且我們執行個體化一個新的ArrayList,其大小設為對象的最大數量。

newObject()方法負責通過PoolObjectFactory.newObject()方法給我們傳遞一個全新的Pool執行個體,或者在freeObjectsArrayList中有對象的情況下,返回一個已入池的執行個體。如果使用這種方法,只要Pool類中有一些Object Storage Service在freeObjects列表中,我們將得到一些可回收的對象。否則,該方法將通過工廠類建立一個新的對象。

free()方法允許我們重新插入不再使用的對象。它的工作就是如果freeObjects列表中沒有滿,就將對象插入到freeObjects列表中。如果列表已滿,則不再添加對象,並且對象可能在free()方法下一次執行時被記憶體回收行程回收。

至於我們如果用Pool類建立一個TouchEvent執行個體,時候不早了,下次再寫

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.