Android游戏开发框架(三)垃圾回收器
2013-02-10 23:35
106 查看
以下均转自Android游戏编程入门经典,转载请标明出处
对于Android开发人员来说,什么是最糟糕的事情?让一切工作都停止运行的垃圾回收!
我们先来看看Input接口
我们从定义两个类开始,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类是实现这种行为的一种很便捷的方式。
Pool<T>这里使用了泛型。这个类是个通用类型的类,泛型允许我们在Pool类中存储任何类型的对象,而无须对类型进行转换。
首先定义的是一个名为PoolObjectFactory的接口,它是泛型的。它只有一个方法createObject(),该方法将返回一个新对象,其具有泛型类型的Pool/PoolObjectFactory实例。
Pool类有3个成员:ArrayList用于存储以入池的对象,PoolObjectFactory用于生成Pool类中包含的类型的新实例,第三个成员用于存放Pool可以容纳的最大对象数量。最后一个成员是必需的,这样Pool才不会无限制增长;否则,我们将可能会遇到一个内存耗尽的异常。
Pool类的构造函数接受一个PoolObjectFactory和所存储对象的最大数量。这两个参数都存储在各自的成员变量里,并且我们实例化一个新的ArrayList,其大小设为对象的最大数量。
newObject()方法负责通过PoolObjectFactory.newObject()方法给我们传递一个全新的Pool实例,或者在freeObjectsArrayList中有对象的情况下,返回一个已入池的实例。如果使用这种方法,只要Pool类中有一些对象存储在freeObjects列表中,我们将得到一些可回收的对象。否则,该方法将通过工厂类创建一个新的对象。
free()方法允许我们重新插入不再使用的对象。它的工作就是如果freeObjects列表中没有满,就将对象插入到freeObjects列表中。如果列表已满,则不再添加对象,并且对象可能在free()方法下一次执行时被垃圾回收器回收。
至于我们如果用Pool类创建一个TouchEvent实例,时候不早了,下次再写
对于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(); else object = 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类中有一些对象存储在freeObjects列表中,我们将得到一些可回收的对象。否则,该方法将通过工厂类创建一个新的对象。
free()方法允许我们重新插入不再使用的对象。它的工作就是如果freeObjects列表中没有满,就将对象插入到freeObjects列表中。如果列表已满,则不再添加对象,并且对象可能在free()方法下一次执行时被垃圾回收器回收。
至于我们如果用Pool类创建一个TouchEvent实例,时候不早了,下次再写
相关文章推荐
- Java(Android)游戏开发框架LGame-0.2.7发布
- Android游戏开发:游戏框架的搭建(4)
- Android游戏开发框架libgdx的使用
- android游戏开发框架libgdx的使用(三)--中文显示与汉字绘制
- android游戏开发框架libgdx的使用(十七)—TiledMap中角色的行动路径
- android游戏开发框架libgdx的使用(四)--舞台和演员
- android游戏开发框架libgdx的使用(十三)—TiledMap中的角色和角色移动
- android游戏开发框架libgdx的使用(七)--开发框架总观
- Android自由的游戏开发框架
- Android游戏开发:游戏框架的搭建(1)
- Android游戏开发:游戏框架的搭建(4)
- 【Android游戏开发之四】Android 游戏框架(一个游戏角色在屏幕行走的demo)
- android游戏开发框架libgdx的使用(十三)—TiledMap中的角色和角色移动
- android游戏开发框架libgdx的使用(十七)—TiledMap中角色的行动路径
- Android游戏开发:游戏框架的搭建(2)
- android游戏开发框架libgdx的使用(四)--舞台和演员
- Android游戏开发的开源框架
- android游戏开发框架libgdx的使用(二十)—资源预加载与AssetManager的使用
- Android游戏开发之构建游戏框架View与SurFaceView的区别(十)
- 【Android游戏开发之四】Android 游戏框架(一个游戏角色在屏幕行走的demo)