分配免费游戏

时间:2010-12-07 14:14:38

标签: java android opengl-es

我的代码基本上是免费分配的,但是当60fps时,GC每30秒运行一次。使用DDMS检查应用程序以进行分配显示已分配了大量SimpleListIterator。还有一些东西被分配,因为我使用Exchanger

SimpleListIterator来自每个循环for (T obj : objs) {}。我的印象是编译器/翻译器会优化那些不使用迭代器来支持它的类型(我基本上只使用ArrayList),但似乎并非如此。

如何避免分配所有这些SimpleListIterators?一种解决方案是切换到常规for循环for (int i = 0; i < size; ++i) {},但我喜欢每个循环:(

另一种方法是扩展ArrayList,它返回一个只分配一次的Iterator

我一起攻击的第三种方法是使用静态辅助函数,该函数返回Collection,它正在重用Iterator。我一起攻击了这样的东西,但铸件感觉非常黑暗和不安全。它应该是线程安全的,因为我使用ThreadLocal?见下文:

public class FastIterator {
    private static ThreadLocal<Holder> holders = new ThreadLocal<Holder>();

    public static <T> Iterable<T> get(ArrayList<T> list) {
        Holder cont = holders.get();

        if (cont == null) {
            cont = new Holder();

            cont.collection = new DummyCollection<T>();
            cont.it = new Iterator<T>();

            holders.set(cont);
        }

        Iterator<T> it = (Iterator<T>) cont.it;
        DummyCollection<T> collection = (DummyCollection<T>) cont.collection;

        it.setList(list);
        collection.setIterator(it);

        return collection;
    }

    private FastIterator() {}

    private static class Holder {
        public DummyCollection<?> collection;
        public Iterator<?> it;
    }

    private static class DummyCollection<T> implements Iterable {
        private Iterator<?> it;

        @Override
        public java.util.Iterator<T> iterator() {
            return (java.util.Iterator<T>) it;
        }

        public void setIterator(Iterator<?> it) {
            this.it = it;
        }
    }

    private static class Iterator<T> implements java.util.Iterator<T> {
        private ArrayList<T> list;
        private int size;
        private int i;

        @Override
        public boolean hasNext() {
            return i < size;
        }

        @Override
        public T next() {
            return list.get(i++);
        }

        @Override
        public void remove() {

        }

        public void setList(ArrayList<T> list) {
            this.list = list;
            size = list.size();
            i = 0;
        }

        private Iterator() {}
    }
}

3 个答案:

答案 0 :(得分:4)

您不应该在Android游戏中使用每个游戏。 我认为这official video也谈到了这一点。

答案 1 :(得分:2)

可能最好的方法是使用Decorator设计。创建一个类,它在构造函数中获取一个集合,并通过调用包装类并重用返回的迭代器来实现Iterable接口。

答案 2 :(得分:0)

避免迭代器分配的另外两种方法。 首先是使用回调习语:

public interface Handler<T> {
  void handle(T element);
}

public interface Handleable<T> {
  void handleAll(Handler<T> handler);
}

public class HandleableList<T> extends ArrayList<T> implements Handleable<T> {
  public void handleAll(Handler<T> handler) {
    for (int i = 0; i < size(); ++i) {
      handler.handle(get(i));
    }
  }
}

这种方法仍然需要一个Handler实例来接收回调,但是这肯定会减少分配,例如,当你试图访问几个列表的元素时。

第二种方法是使用游标习语:

public interface Cursor<T> {
  void reset();
  boolean next();
  T current();
}

public class CursoredList<T> extends ArrayList<T> implements Cursor<T> {
  private int _index = -1;

  public void reset() {
    _index = -1;
  }

  public boolean next() {
    return ++_index >= size();
  }

  public T current() {
    return get(_index);
  }
}

当然,这与在ArrayList的子类型上实现Iterable和Iterator相同,但这清楚地将光标位置显示为集合本身的状态。