10、Libgdx的内存管理

(官网:www.libgdx.cn

游戏是非常耗资源的应用。图片和音效可能耗费大量的内存,另一方面来说,这些资源没有被Java垃圾回收,让一个垃圾处理来决定将显存中的5M的图片进行释放也不是一个明知的选择。

我们希望尽可能的在生命周期内管理好我们的资源。在Libgdx中有多个类来表示这些资源。它们都统一继承一Disposable接口,这个类对需要释放的资源进行管理。释放资源失败将会导致内存泄漏。
这些类需要手动进行释放(可能不完整):

  • AssetManager
  • Bitmap
  • BitmapFont
  • BitmapFontCache
  • CameraGroupStrategy
  • DecalBatch
  • ETC1Data
  • FrameBuffer
  • Mesh
  • Model
  • ModelBatch
  • ParticleEffect
  • Pixmap
  • PixmapPacker
  • Shader
  • ShaderProgram
  • Shape
  • Skin
  • SpriteBatch
  • SpriteCache
  • Stage
  • Texture
  • TextureAtlas
  • TileAtlas
  • TileMapRenderer
  • com.badlogic.gdx.physics.box2d.World
  • 所有的bullet类

资源文件要在不使用是尽快的释放,访问释放的资源将会导致错误。要确保这样的事情不要发生。
要判断一个特定的类是否需要释放,可以看一下它有没有disposed()方法,如果有,则需要释放。

对象轮询

对象轮询是重复利用未激活或者“死掉”的对象的基本原则,而不是每次都创建新的对象。可以通过创建一个对象池来完成,当你需要一个新的对象是,你可以从对象池中获取。如果池中有可用的对象,就返回,如果池是空的或者不包含可用的对象,将会创建一个新的对象的实例并返回。当你不需要一个对象时,需要进行释放,这就意味着将对象返回到池中。通过这种方式达到分配内存的重复利用。

这在游戏的内存管理中至关重要。

Libgdx提供了一系列的工具来实现简单的轮询。

  • Poolable接口
  • Pool
  • Pools
    继承Poolable接口意味着你需要在你的对象中有一个reset()方法。这个方法可以自动调用释放你的对象。

以下是一个简单的示例:

 public class Bullet implements Poolable {
public Vector2 position;
public boolean alive;
/**
 * 构造器,初始化.
 */
public Bullet() {
    this.position = new Vector2();
    this.alive = false;
}
/**
 * 初始化,从对象池中获取
 */
public void init(float posX, float posY) {
    position.set(posX,  posY);
    alive = true;
}
/**
 * 回调方法
 */
@Override
public void reset() {
    position.set(0,0);
    alive = false;
}
/**
 *更新
 */
public void update (float delta) {
    // 更新位置
    position.add(1*delta*60, 1*delta*60);
    // 屏幕之外,设置为dead
    if (isOutOfScreen()) alive = false;
}

}

在游戏的world类中:

public class World {
// Bullet类
private final Array<Bullet> activeBullets = new Array<Bullet>();
// bullet池
private final Pool<Bullet> bulletPool = new Pool<Bullet>() {
@Override
protected Bullet newObject() {
    return new Bullet();
}
};

public void update(float delta) {
    // 新的Bullet
    Bullet item = bulletPool.obtain();
    item.init(2, 2);
    activeBullets.add(item);
    //释放bullet
    Bullet item;
    int len = activeBullets.size;
    for (int i = len; --i >= 0;) {
        item = activeBullets.get(i);
        if (item.alive == false) {
            activeBullets.removeIndex(i);
            bulletPool.free(item);
        }
    }
}

}

Pools类中提供了静态方法来动态的创建任何对象的池。如下:

private final Pool<Bullet> bulletPool = Pools.get(Bullet.class);

怎样使用Pool

一个Pool<>管理一个单独类型的对象。从一个特定的Pool实例中取出,然后释放之后返回到Pool中。对象可能会实现Poolable接口,这将会在对象返回到Pool中自动进行重置。对象将按需分配。

你必须实现你自己的Pool<>子类,因为newObject方法是抽象的。

www.libgdx.cn版权所有,如需转载,注明出处)

时间: 2024-12-24 11:36:55

10、Libgdx的内存管理的相关文章

第九章 Libgdx内存管理

Android游戏开发群:290051794 Libgdx游戏开发框架交流群:261954621   游戏是使用资源较多的应用.图像和音效会占用大量的内存.此外,这些资源大部分不是通过java的垃圾回收器管理,而是由本地驱动管理.使用垃圾回收器对纹理等进行回收不是一个明智的做法. 我们需要合理的控制资源的生命周期.在Libgdx中有多个类实现这个功能.它们都实现Disposable接口指明在生命周期结束后要销毁的类的实例.错误的释放资源会导致内存泄露. 下面的类需要手工处理: AssetMana

Java进阶10 内存管理与垃圾回收

作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢!   整个教程中已经不时的出现一些内存管理和垃圾回收的相关知识.这里进行一个小小的总结. Java是在JVM所虚拟出的内存环境中运行的.内存分为栈(stack)和堆(heap)两部分.我们将分别考察这两个区域.   栈 栈的基本概念参考纸上谈兵: 栈 (stack).许多语言利用栈数据结构来记录函数调用的次序和相关变量(参考Linux从程序到进程). 在Java中,JVM中的栈记录

C# 语言规范--1.4 自动内存管理

规范 手动内存管理要求开发人员管理内存块的分配和回收.手动内存管理可能既耗时又麻烦.在 C# 中提供了自动内存管理,使开发人员从这个繁重的任务中解脱出来.在绝大多数情况下,自动内存管理可以提高代码质量和开发人员的工作效率,并且不会对表达能力或性能造成负面影响. 示例 using System; public class Stack {    private Node first = null;    public bool Empty {       get {          return

[share]深入探讨PHP中的内存管理问题

一. 内存 在PHP中,填充一个字符串变量相当简单,这只需要一个语句"<?php $str = "hello world "; ?>"即可,并且该字符串能够被自由地修改.拷贝和移动.而在C语言中,尽管你能够编写例如"char *str = "hello world ";"这样的一个简单的静态字符串:但是,却不能修改该字符串,因为它生存于程序空间内.为了创建一个可操纵的字符串,你必须分配一个内存块,并且通过一个函数(

通过案例深入探讨PHP中的内存管理问题

问题  内存管理对于长期运行的程序,例如服务器守护程序,是相当重要的影响:因此,理解PHP是如何分配与释放内存的对于创建这类程序极为重要.本文将重点探讨PHP的内存管理问题. 一. 内存 在PHP中,填充一个字符串变量相当简单,这只需要一个语句"<?php $str = 'hello world '; ?>"即可,并且该字符串能够被自由地修改.拷贝和移动.而在C语言中,尽管你能够编写例如"char *str = "hello world ";&

深入探讨PHP中的内存管理问题

摘要 内存管理对于长期运行的程序,例如服务器守护程序,是相当重要的影响:因此,理解PHP是如何分配与释放内存的对于创建这类程序极为重要.本文将重点探讨PHP的内存管理问题. 一. 内存 在PHP中,填充一个字符串变量相当简单,这只需要一个语句"<?php $str = 'hello world '; ?>"即可,并且该字符串能够被自由地修改.拷贝和移动.而在C语言中,尽管你能够编写例如"char *str = "hello world ";&q

JVM内存管理:GC算法精解---分代搜集算法

引言 何为终极算法? 其实就是现在的JVM采用的算法,并非真正的终极.说不定若干年以后,还会有新的终极算法,而且几乎是一定会有,因为LZ相信高人们的能力. 那么分代搜集算法是怎么处理GC的呢? 对象分类 上一章已经说过,分代搜集算法是针对对象的不同特性,而使用适合的算法,这里面并没有实际上的新算法产生.与其说分代搜集算法是第四个算法,不如说它是对前三个算法的实际应用. 首先我们来探讨一下对象的不同特性,接下来LZ和各位来一起给这些对象选择GC算法. 内存中的对象按照生命周期的长短大致可以分为三种

JVM内存管理:杂谈(借此也论一论obj=null)

各位园友好,LZ是从某网站转战过来的博主,看到这里很多博主都称看友们为园友,LZ斗胆模仿一下,不过以前,LZ其实都是称看友们为猿友的.之前LZ在某网站已经写了一系列文章,已经全部复制到了园内的新博客,主要是设计模式的内容,各位有兴趣的也可以去翻看一下,其中有不少还是颇受之前猿友们喜爱的. 作为一个程序猿,修炼的过程就犹如玄幻小说中的主角,不仅需要练习各种武技,内气的修炼的一样重要.虽然武技可以迅速的提升主角的实力,但是在内气太差的情况下,根本发挥不出武技的十之一二. 因此,在介绍过设计模式这一类

WINX窗口类对象的内存管理

为了引入WINX窗口类对象的内存管理(生命周期模型),我绕了一大圈子.实在是,内存 管理太重要了,花多少口舌介绍它都不过分.我曾经见到这样一句话:"C++程序员觉得 内存管理太重要了,所以一定要自己进行管理:Java/C#程序员觉得内存管理太重要了,所以 一定不能自己去管理".从某种意义上说,两者都是对的. 那么WINX的窗口对象是否也是采用gc allocator呢? 答:不是. 具体问题具体分析.在通常情况下,我个人确实已经非常习惯使用gc allocator来进行内 存管理,但是